You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by nn...@apache.org on 2020/06/25 20:33:40 UTC

[geode] branch support/1.13 updated: GEODE-8287: Added another condition to cause the indexed value to be used

This is an automated email from the ASF dual-hosted git repository.

nnag pushed a commit to branch support/1.13
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/support/1.13 by this push:
     new 133229a  GEODE-8287: Added another condition to cause the indexed value to be used
133229a is described below

commit 133229a4c98d6e64b138d5cd73e3ac7905797b3d
Author: Barry Oglesby <bo...@users.noreply.github.com>
AuthorDate: Thu Jun 25 05:58:46 2020 -1000

    GEODE-8287: Added another condition to cause the indexed value to be used
    
    (cherry picked from commit 827f8651b02d90a8ad7dfa3dca62af3c06ca6b6c)
---
 .../IndexUsageInJoinQueryDistributedTest.java      | 215 +++++++++++++++++++++
 .../geode/cache/query/internal/QueryUtils.java     |   3 +
 2 files changed, 218 insertions(+)

diff --git a/geode-core/src/distributedTest/java/org/apache/geode/cache/query/dunit/IndexUsageInJoinQueryDistributedTest.java b/geode-core/src/distributedTest/java/org/apache/geode/cache/query/dunit/IndexUsageInJoinQueryDistributedTest.java
new file mode 100644
index 0000000..113a532
--- /dev/null
+++ b/geode-core/src/distributedTest/java/org/apache/geode/cache/query/dunit/IndexUsageInJoinQueryDistributedTest.java
@@ -0,0 +1,215 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.cache.query.dunit;
+
+import static org.apache.geode.cache.RegionShortcut.REPLICATE;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.cache.Cache;
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.client.ClientCache;
+import org.apache.geode.cache.client.ClientRegionShortcut;
+import org.apache.geode.cache.query.IndexExistsException;
+import org.apache.geode.cache.query.IndexNameConflictException;
+import org.apache.geode.cache.query.Query;
+import org.apache.geode.cache.query.QueryService;
+import org.apache.geode.cache.query.RegionNotFoundException;
+import org.apache.geode.distributed.internal.DistributionStats;
+import org.apache.geode.distributed.internal.InternalDistributedSystem;
+import org.apache.geode.pdx.PdxReader;
+import org.apache.geode.pdx.PdxSerializable;
+import org.apache.geode.pdx.PdxWriter;
+import org.apache.geode.test.dunit.rules.ClientVM;
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+import org.apache.geode.test.junit.categories.OQLIndexTest;
+import org.apache.geode.test.junit.rules.serializable.SerializableTestName;
+
+@Category({OQLIndexTest.class})
+public class IndexUsageInJoinQueryDistributedTest implements Serializable {
+
+  private MemberVM locator;
+
+  private MemberVM server;
+
+  private ClientVM client;
+
+  private static final String PRODUCT_REGION_NAME = "product";
+
+  private static final String INSTRUMENT_REGION_NAME = "instrument";
+
+  @Rule
+  public ClusterStartupRule clusterRule = new ClusterStartupRule();
+
+  @Rule
+  public SerializableTestName testName = new SerializableTestName();
+
+  @Test
+  public void testSecondIndexUsedWhenExecutingJoinQuery() throws Exception {
+    // Start Locator
+    locator = clusterRule.startLocatorVM(0);
+
+    // Start server
+    server = clusterRule.startServerVM(1, locator.getPort());
+
+    // Create server regions
+    server.invoke(() -> createServerRegionsAndIndexes());
+
+    // Start client
+    client = clusterRule.startClientVM(2, c -> c.withLocatorConnection(locator.getPort()));
+
+    // Create client regions
+    client.invoke(() -> createClientRegions());
+
+    // Load regions
+    int numProducts = 1000;
+    int numInstruments = 100;
+    client.invoke(() -> loadRegions(numProducts, numInstruments));
+
+    // Get number of deserializations before query
+    long deserializationsBeforeQuery = server.invoke(() -> getDeserializations());
+
+    // Execute query
+    client.invoke(() -> executeQuery(numInstruments));
+
+    // Get number of deserializations after query
+    long deserializationsAfterQuery = server.invoke(() -> getDeserializations());
+
+    // Verify number of deserializations during query
+    // 1 for each instrument in the instrumentTypesIndex (100)
+    // For each instrument, 1 product in the productIdKeyIndex (100)
+    // 1 for the bind parameter
+    assertThat(deserializationsAfterQuery - deserializationsBeforeQuery)
+        .isEqualTo((numInstruments * 2) + 1);
+  }
+
+  private void createServerRegionsAndIndexes()
+      throws RegionNotFoundException, IndexNameConflictException, IndexExistsException {
+    Cache cache = ClusterStartupRule.getCache();
+    QueryService queryService = cache.getQueryService();
+    Region productRegion = cache.createRegionFactory(REPLICATE).create(PRODUCT_REGION_NAME);
+    queryService.createKeyIndex("productIdKeyIndex", "productId", productRegion.getFullPath());
+    Region instrumentRegion = cache.createRegionFactory(REPLICATE).create(INSTRUMENT_REGION_NAME);
+    queryService.createIndex("instrumentTypesIndex", "types['TYPE']",
+        instrumentRegion.getFullPath());
+  }
+
+  private void createClientRegions() {
+    ClientCache cache = ClusterStartupRule.getClientCache();
+    cache.createClientRegionFactory(ClientRegionShortcut.PROXY).create(PRODUCT_REGION_NAME);
+    cache.createClientRegionFactory(ClientRegionShortcut.PROXY).create(INSTRUMENT_REGION_NAME);
+  }
+
+  private void loadRegions(int numProducts, int numInstruments) {
+    ClientCache cache = ClusterStartupRule.getClientCache();
+    Region productRegion = cache.getRegion(PRODUCT_REGION_NAME);
+    Region instrumentRegion = cache.getRegion(INSTRUMENT_REGION_NAME);
+
+    // Load product region
+    for (int i = 0; i < numProducts; i++) {
+      String productId = String.valueOf(i);
+      Product product = new Product(productId);
+      productRegion.put(productId, product);
+    }
+
+    // Load instrument region
+    for (int i = 0; i < numInstruments; i++) {
+      String instrumentId = String.valueOf(i);
+      Map<String, String> types = new HashMap<>();
+      types.put("TYPE", "TYPE1");
+      Instrument instrument = new Instrument(instrumentId, "0", types);
+      instrumentRegion.put(instrumentId, instrument);
+    }
+  }
+
+  private void executeQuery(int numInstruments) throws Exception {
+    ClientCache cache = ClusterStartupRule.getClientCache();
+    Region productRegion = cache.getRegion(PRODUCT_REGION_NAME);
+    Region instrumentRegion = cache.getRegion(INSTRUMENT_REGION_NAME);
+    String queryString =
+        "<trace> select i,p from " + instrumentRegion.getFullPath() + " i, "
+            + productRegion.getFullPath()
+            + " p where i.productId = p.productId and i.types['TYPE']=$1";
+    Query query = ClusterStartupRule.getClientCache().getQueryService().newQuery(queryString);
+    Collection results = (Collection) query.execute(new Object[] {"TYPE1"});
+    assertThat(results.size()).isEqualTo(numInstruments);
+  }
+
+  private long getDeserializations() {
+    DistributionStats distributionStats =
+        (DistributionStats) ((InternalDistributedSystem) ClusterStartupRule.getCache()
+            .getDistributedSystem()).getDistributionManager().getStats();
+    return distributionStats.getStats().getLong("deserializations");
+  }
+
+  public static class Product implements PdxSerializable {
+
+    public String productId;
+
+    public Product() {}
+
+    public Product(String productId) {
+      this.productId = productId;
+    }
+
+    @Override
+    public void toData(PdxWriter writer) {
+      writer.writeString("productId", productId);
+    }
+
+    @Override
+    public void fromData(PdxReader reader) {
+      productId = reader.readString("productId");
+    }
+  }
+
+  public static class Instrument implements PdxSerializable {
+
+    private Map<String, String> types;
+    private String instrumentId;
+    private String productId;
+
+    public Instrument() {}
+
+    public Instrument(String instrumentId, String productId, Map<String, String> types) {
+      this.instrumentId = instrumentId;
+      this.productId = productId;
+      this.types = types;
+    }
+
+    @Override
+    public void toData(PdxWriter writer) {
+      writer.writeString("instrumentId", instrumentId);
+      writer.writeString("productId", productId);
+      writer.writeObject("types", types);
+    }
+
+    @Override
+    public void fromData(PdxReader reader) {
+      instrumentId = reader.readString("instrumentId");
+      productId = reader.readString("productId");
+      types = (Map<String, String>) reader.readObject("types");
+    }
+  }
+}
diff --git a/geode-core/src/main/java/org/apache/geode/cache/query/internal/QueryUtils.java b/geode-core/src/main/java/org/apache/geode/cache/query/internal/QueryUtils.java
index 29446bf..ccae99d 100644
--- a/geode-core/src/main/java/org/apache/geode/cache/query/internal/QueryUtils.java
+++ b/geode-core/src/main/java/org/apache/geode/cache/query/internal/QueryUtils.java
@@ -737,6 +737,9 @@ public class QueryUtils {
         } else {
           c = currentLevel.evaluateCollection(context);
         }
+      } else if (useDerivedResults && derivedResults != null && key != null
+          && derivedResults.containsKey(key)) {
+        c = derivedResults.get(key);
       } else {
         c = currentLevel.evaluateCollection(context);
       }