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

cwylie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git


The following commit(s) were added to refs/heads/master by this push:
     new 7fb1153bba add virtual columns to search query cache key (#12907)
7fb1153bba is described below

commit 7fb1153bba73bbb1ae245a8acc7bf605463ed725
Author: Clint Wylie <[email protected]>
AuthorDate: Wed Aug 17 20:26:01 2022 -0700

    add virtual columns to search query cache key (#12907)
    
    * add virtual columns to search query cache key
---
 .../apache/druid/query/cache/CacheKeyBuilder.java  | 43 ++++-------
 .../query/search/SearchQueryQueryToolChest.java    | 47 +++---------
 .../apache/druid/query/search/SearchQuerySpec.java |  5 +-
 .../apache/druid/query/search/SearchSortSpec.java  |  4 +-
 .../segment/virtual/NestedFieldVirtualColumn.java  |  1 +
 .../search/SearchQueryQueryToolChestTest.java      | 86 +++++++++++++++++++++-
 6 files changed, 113 insertions(+), 73 deletions(-)

diff --git 
a/core/src/main/java/org/apache/druid/query/cache/CacheKeyBuilder.java 
b/core/src/main/java/org/apache/druid/query/cache/CacheKeyBuilder.java
index c40cbebe15..fca068e02c 100644
--- a/core/src/main/java/org/apache/druid/query/cache/CacheKeyBuilder.java
+++ b/core/src/main/java/org/apache/druid/query/cache/CacheKeyBuilder.java
@@ -113,48 +113,30 @@ public class CacheKeyBuilder
     }
   }
 
-  private static byte[] stringCollectionToByteArray(Collection<String> input, 
boolean preserveOrder)
+  private static byte[] stringCollectionToByteArray(
+      @Nullable Collection<String> input,
+      boolean preserveOrder
+  )
   {
-    return collectionToByteArray(
-        input,
-        new Function<String, byte[]>()
-        {
-          @Override
-          public byte[] apply(@Nullable String input)
-          {
-            return StringUtils.toUtf8WithNullToEmpty(input);
-          }
-        },
-        STRING_SEPARATOR,
-        preserveOrder
-    );
+    return collectionToByteArray(input, StringUtils::toUtf8WithNullToEmpty, 
STRING_SEPARATOR, preserveOrder);
   }
 
-  private static byte[] cacheableCollectionToByteArray(Collection<? extends 
Cacheable> input, boolean preserveOrder)
+  private static byte[] cacheableCollectionToByteArray(
+      @Nullable Collection<? extends Cacheable> input,
+      boolean preserveOrder
+  )
   {
-    return collectionToByteArray(
-        input,
-        new Function<Cacheable, byte[]>()
-        {
-          @Override
-          public byte[] apply(@Nullable Cacheable input)
-          {
-            return input == null ? EMPTY_BYTES : input.getCacheKey();
-          }
-        },
-        EMPTY_BYTES,
-        preserveOrder
-    );
+    return collectionToByteArray(input, CacheKeyBuilder::cacheableToByteArray, 
EMPTY_BYTES, preserveOrder);
   }
 
   private static <T> byte[] collectionToByteArray(
-      Collection<? extends T> collection,
+      @Nullable Collection<? extends T> collection,
       Function<T, byte[]> serializeFunction,
       byte[] separator,
       boolean preserveOrder
   )
   {
-    if (collection.size() > 0) {
+    if (collection != null && collection.size() > 0) {
       List<byte[]> byteArrayList = 
Lists.newArrayListWithCapacity(collection.size());
       int totalByteLength = 0;
       for (T eachItem : collection) {
@@ -184,6 +166,7 @@ public class CacheKeyBuilder
     }
   }
 
+
   private final List<Item> items = new ArrayList<>();
   private final byte id;
   private int size;
diff --git 
a/processing/src/main/java/org/apache/druid/query/search/SearchQueryQueryToolChest.java
 
b/processing/src/main/java/org/apache/druid/query/search/SearchQueryQueryToolChest.java
index 4f0563317d..ff3c5b8e01 100644
--- 
a/processing/src/main/java/org/apache/druid/query/search/SearchQueryQueryToolChest.java
+++ 
b/processing/src/main/java/org/apache/druid/query/search/SearchQueryQueryToolChest.java
@@ -26,7 +26,6 @@ import com.google.common.base.Functions;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
-import com.google.common.primitives.Ints;
 import com.google.inject.Inject;
 import org.apache.druid.java.util.common.DateTimes;
 import org.apache.druid.java.util.common.IAE;
@@ -42,12 +41,11 @@ import org.apache.druid.query.QueryToolChest;
 import org.apache.druid.query.Result;
 import org.apache.druid.query.ResultGranularTimestampComparator;
 import org.apache.druid.query.aggregation.MetricManipulationFn;
+import org.apache.druid.query.cache.CacheKeyBuilder;
 import org.apache.druid.query.context.ResponseContext;
 import org.apache.druid.query.dimension.DimensionSpec;
-import org.apache.druid.query.filter.DimFilter;
 
 import javax.annotation.Nullable;
-import java.nio.ByteBuffer;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -147,41 +145,14 @@ public class SearchQueryQueryToolChest extends 
QueryToolChest<Result<SearchResul
       @Override
       public byte[] computeCacheKey(SearchQuery query)
       {
-        final DimFilter dimFilter = query.getDimensionsFilter();
-        final byte[] filterBytes = dimFilter == null ? new byte[]{} : 
dimFilter.getCacheKey();
-        final byte[] querySpecBytes = query.getQuery().getCacheKey();
-        final byte[] granularityBytes = query.getGranularity().getCacheKey();
-
-        final List<DimensionSpec> dimensionSpecs =
-            query.getDimensions() != null ? query.getDimensions() : 
Collections.emptyList();
-        final byte[][] dimensionsBytes = new byte[dimensionSpecs.size()][];
-        int dimensionsBytesSize = 0;
-        int index = 0;
-        for (DimensionSpec dimensionSpec : dimensionSpecs) {
-          dimensionsBytes[index] = dimensionSpec.getCacheKey();
-          dimensionsBytesSize += dimensionsBytes[index].length;
-          ++index;
-        }
-
-        final byte[] sortSpecBytes = query.getSort().getCacheKey();
-
-        final ByteBuffer queryCacheKey = ByteBuffer
-            .allocate(
-                1 + 4 + granularityBytes.length + filterBytes.length +
-                querySpecBytes.length + dimensionsBytesSize + 
sortSpecBytes.length
-            )
-            .put(SEARCH_QUERY)
-            .put(Ints.toByteArray(query.getLimit()))
-            .put(granularityBytes)
-            .put(filterBytes)
-            .put(querySpecBytes)
-            .put(sortSpecBytes);
-
-        for (byte[] bytes : dimensionsBytes) {
-          queryCacheKey.put(bytes);
-        }
-
-        return queryCacheKey.array();
+        return new CacheKeyBuilder(SEARCH_QUERY).appendInt(query.getLimit())
+                                                
.appendCacheable(query.getGranularity())
+                                                
.appendCacheable(query.getFilter())
+                                                
.appendCacheable(query.getQuery())
+                                                
.appendCacheable(query.getSort())
+                                                
.appendCacheables(query.getDimensions())
+                                                
.appendCacheable(query.getVirtualColumns())
+                                                .build();
       }
 
       @Override
diff --git 
a/processing/src/main/java/org/apache/druid/query/search/SearchQuerySpec.java 
b/processing/src/main/java/org/apache/druid/query/search/SearchQuerySpec.java
index ae2be73c27..ecc236d3b1 100644
--- 
a/processing/src/main/java/org/apache/druid/query/search/SearchQuerySpec.java
+++ 
b/processing/src/main/java/org/apache/druid/query/search/SearchQuerySpec.java
@@ -22,6 +22,7 @@ package org.apache.druid.query.search;
 import com.fasterxml.jackson.annotation.JsonSubTypes;
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import org.apache.druid.annotations.SubclassesMustOverrideEqualsAndHashCode;
+import org.apache.druid.java.util.common.Cacheable;
 
 import javax.annotation.Nullable;
 
@@ -36,9 +37,7 @@ import javax.annotation.Nullable;
     @JsonSubTypes.Type(name = "all", value = AllSearchQuerySpec.class)
 })
 @SubclassesMustOverrideEqualsAndHashCode
-public interface SearchQuerySpec
+public interface SearchQuerySpec extends Cacheable
 {
   boolean accept(@Nullable String dimVal);
-
-  byte[] getCacheKey();
 }
diff --git 
a/processing/src/main/java/org/apache/druid/query/search/SearchSortSpec.java 
b/processing/src/main/java/org/apache/druid/query/search/SearchSortSpec.java
index a7aa2250ba..e97414a7c3 100644
--- a/processing/src/main/java/org/apache/druid/query/search/SearchSortSpec.java
+++ b/processing/src/main/java/org/apache/druid/query/search/SearchSortSpec.java
@@ -21,13 +21,14 @@ package org.apache.druid.query.search;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.druid.java.util.common.Cacheable;
 import org.apache.druid.java.util.common.StringUtils;
 import org.apache.druid.query.ordering.StringComparator;
 import org.apache.druid.query.ordering.StringComparators;
 
 import java.util.Comparator;
 
-public class SearchSortSpec
+public class SearchSortSpec implements Cacheable
 {
   public static final StringComparator DEFAULT_ORDERING = 
StringComparators.LEXICOGRAPHIC;
 
@@ -66,6 +67,7 @@ public class SearchSortSpec
     };
   }
 
+  @Override
   public byte[] getCacheKey()
   {
     return ordering.getCacheKey();
diff --git 
a/processing/src/main/java/org/apache/druid/segment/virtual/NestedFieldVirtualColumn.java
 
b/processing/src/main/java/org/apache/druid/segment/virtual/NestedFieldVirtualColumn.java
index ad017d910f..13703cf9f2 100644
--- 
a/processing/src/main/java/org/apache/druid/segment/virtual/NestedFieldVirtualColumn.java
+++ 
b/processing/src/main/java/org/apache/druid/segment/virtual/NestedFieldVirtualColumn.java
@@ -144,6 +144,7 @@ public class NestedFieldVirtualColumn implements 
VirtualColumn
   {
     final String partsString = NestedPathFinder.toNormalizedJsonPath(parts);
     return new 
CacheKeyBuilder(VirtualColumnCacheHelper.CACHE_TYPE_ID_USER_DEFINED).appendString("nested-field")
+                                                                               
    .appendString(outputName)
                                                                                
    .appendString(columnName)
                                                                                
    .appendString(partsString)
                                                                                
    .appendBoolean(processFromRaw)
diff --git 
a/processing/src/test/java/org/apache/druid/query/search/SearchQueryQueryToolChestTest.java
 
b/processing/src/test/java/org/apache/druid/query/search/SearchQueryQueryToolChestTest.java
index 8ef0ff3548..fc2f4d2493 100644
--- 
a/processing/src/test/java/org/apache/druid/query/search/SearchQueryQueryToolChestTest.java
+++ 
b/processing/src/test/java/org/apache/druid/query/search/SearchQueryQueryToolChestTest.java
@@ -29,12 +29,18 @@ import org.apache.druid.query.CacheStrategy;
 import org.apache.druid.query.Druids;
 import org.apache.druid.query.Result;
 import org.apache.druid.query.TableDataSource;
+import org.apache.druid.query.expression.TestExprMacroTable;
 import org.apache.druid.query.spec.MultipleIntervalSegmentSpec;
 import org.apache.druid.segment.VirtualColumns;
+import org.apache.druid.segment.column.ColumnType;
+import org.apache.druid.segment.virtual.ExpressionVirtualColumn;
+import org.apache.druid.testing.InitializedNullHandlingTest;
 import org.junit.Assert;
 import org.junit.Test;
 
-public class SearchQueryQueryToolChestTest
+import java.util.Arrays;
+
+public class SearchQueryQueryToolChestTest extends InitializedNullHandlingTest
 {
 
   @Test
@@ -75,4 +81,82 @@ public class SearchQueryQueryToolChestTest
 
     Assert.assertEquals(result, fromCacheResult);
   }
+
+  @Test
+  public void testCacheStrategyVirtualColumns()
+  {
+    SearchQueryQueryToolChest toolChest = new SearchQueryQueryToolChest(null, 
null);
+    SearchQuery query1 = new SearchQuery(
+        new TableDataSource("dummy"),
+        null,
+        Granularities.ALL,
+        1,
+        new 
MultipleIntervalSegmentSpec(ImmutableList.of(Intervals.of("2015-01-01/2015-01-02"))),
+        ImmutableList.of(Druids.DIMENSION_IDENTITY.apply("v0")),
+        VirtualColumns.create(
+            ImmutableList.of(
+                new ExpressionVirtualColumn("v0", "concat(dim1, 'foo')", 
ColumnType.STRING, TestExprMacroTable.INSTANCE)
+            )
+        ),
+        new FragmentSearchQuerySpec(ImmutableList.of("a", "b")),
+        null,
+        null
+    );
+
+    SearchQuery query2 = new SearchQuery(
+        new TableDataSource("dummy"),
+        null,
+        Granularities.ALL,
+        1,
+        new 
MultipleIntervalSegmentSpec(ImmutableList.of(Intervals.of("2015-01-01/2015-01-02"))),
+        ImmutableList.of(Druids.DIMENSION_IDENTITY.apply("v0")),
+        VirtualColumns.create(
+            ImmutableList.of(
+                new ExpressionVirtualColumn("v0", "concat(dim2, 'foo')", 
ColumnType.STRING, TestExprMacroTable.INSTANCE)
+            )
+        ),
+        new FragmentSearchQuerySpec(ImmutableList.of("a", "b")),
+        null,
+        null
+    );
+
+    SearchQuery query3 = new SearchQuery(
+        new TableDataSource("dummy"),
+        null,
+        Granularities.ALL,
+        1,
+        new 
MultipleIntervalSegmentSpec(ImmutableList.of(Intervals.of("2015-01-01/2015-01-02"))),
+        ImmutableList.of(Druids.DIMENSION_IDENTITY.apply("v0")),
+        VirtualColumns.create(
+            ImmutableList.of(
+                new ExpressionVirtualColumn("v0", "concat(dim1, 'foo')", 
ColumnType.STRING, TestExprMacroTable.INSTANCE)
+            )
+        ),
+        new FragmentSearchQuerySpec(ImmutableList.of("a", "b")),
+        null,
+        null
+    );
+
+    Assert.assertArrayEquals(
+        toolChest.getCacheStrategy(query1).computeCacheKey(query1),
+        toolChest.getCacheStrategy(query1).computeCacheKey(query1)
+    );
+
+    Assert.assertArrayEquals(
+        toolChest.getCacheStrategy(query2).computeCacheKey(query2),
+        toolChest.getCacheStrategy(query2).computeCacheKey(query2)
+    );
+
+    Assert.assertArrayEquals(
+        toolChest.getCacheStrategy(query1).computeCacheKey(query1),
+        toolChest.getCacheStrategy(query3).computeCacheKey(query3)
+    );
+
+    Assert.assertFalse(
+        Arrays.equals(
+            toolChest.getCacheStrategy(query1).computeCacheKey(query1),
+            toolChest.getCacheStrategy(query2).computeCacheKey(query2)
+        )
+    );
+  }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to