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

gian 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 f82463dcc43 fix: spectatorHistogram null handling (#18122)
f82463dcc43 is described below

commit f82463dcc437f9c458c7546716d7ca4d91c5eaf1
Author: Hiroshi Fukada <[email protected]>
AuthorDate: Tue Oct 28 11:40:24 2025 -0400

    fix: spectatorHistogram null handling (#18122)
---
 ...SpectatorHistogramPercentilePostAggregator.java |   3 +
 ...pectatorHistogramPercentilesPostAggregator.java |   3 +
 .../SpectatorHistogramAggregatorTest.java          | 101 +++++++++++++++++++++
 3 files changed, 107 insertions(+)

diff --git 
a/extensions-contrib/spectator-histogram/src/main/java/org/apache/druid/spectator/histogram/SpectatorHistogramPercentilePostAggregator.java
 
b/extensions-contrib/spectator-histogram/src/main/java/org/apache/druid/spectator/histogram/SpectatorHistogramPercentilePostAggregator.java
index 80854c57d46..29da04c67cc 100644
--- 
a/extensions-contrib/spectator-histogram/src/main/java/org/apache/druid/spectator/histogram/SpectatorHistogramPercentilePostAggregator.java
+++ 
b/extensions-contrib/spectator-histogram/src/main/java/org/apache/druid/spectator/histogram/SpectatorHistogramPercentilePostAggregator.java
@@ -90,6 +90,9 @@ public class SpectatorHistogramPercentilePostAggregator 
implements PostAggregato
   public Object compute(final Map<String, Object> combinedAggregators)
   {
     final SpectatorHistogram sketch = (SpectatorHistogram) 
field.compute(combinedAggregators);
+    if (sketch == null) {
+      return null;
+    }
     return sketch.getPercentileValue(percentile);
   }
 
diff --git 
a/extensions-contrib/spectator-histogram/src/main/java/org/apache/druid/spectator/histogram/SpectatorHistogramPercentilesPostAggregator.java
 
b/extensions-contrib/spectator-histogram/src/main/java/org/apache/druid/spectator/histogram/SpectatorHistogramPercentilesPostAggregator.java
index ae6d9392644..51370d9038c 100644
--- 
a/extensions-contrib/spectator-histogram/src/main/java/org/apache/druid/spectator/histogram/SpectatorHistogramPercentilesPostAggregator.java
+++ 
b/extensions-contrib/spectator-histogram/src/main/java/org/apache/druid/spectator/histogram/SpectatorHistogramPercentilesPostAggregator.java
@@ -86,6 +86,9 @@ public class SpectatorHistogramPercentilesPostAggregator 
implements PostAggregat
   public Object compute(final Map<String, Object> combinedAggregators)
   {
     final SpectatorHistogram sketch = (SpectatorHistogram) 
field.compute(combinedAggregators);
+    if (sketch == null) {
+      return null;
+    }
     return sketch.getPercentileValues(percentiles);
   }
 
diff --git 
a/extensions-contrib/spectator-histogram/src/test/java/org/apache/druid/spectator/histogram/SpectatorHistogramAggregatorTest.java
 
b/extensions-contrib/spectator-histogram/src/test/java/org/apache/druid/spectator/histogram/SpectatorHistogramAggregatorTest.java
index 88e710645d1..15979b94376 100644
--- 
a/extensions-contrib/spectator-histogram/src/test/java/org/apache/druid/spectator/histogram/SpectatorHistogramAggregatorTest.java
+++ 
b/extensions-contrib/spectator-histogram/src/test/java/org/apache/druid/spectator/histogram/SpectatorHistogramAggregatorTest.java
@@ -783,6 +783,107 @@ public class SpectatorHistogramAggregatorTest extends 
InitializedNullHandlingTes
     Assert.assertEquals(n * segments.size(), (Double) results.get(0).get(1), 
0.001);
   }
 
+  @Test
+  public void testPercentilePostAggregatorWithNullSketch() throws Exception
+  {
+    Sequence<ResultRow> seq = helper.createIndexAndRunQueryOnSegment(
+        new 
File(this.getClass().getClassLoader().getResource("input_data.tsv").getFile()),
+        INPUT_DATA_PARSE_SPEC,
+        String.join(
+            "\n",
+            "[",
+            "  {\"type\": \"spectatorHistogram\", \"name\": \"histogram\", 
\"fieldName\": \"cost\"}",
+            "]"
+        ),
+        0, // minTimestamp
+        Granularities.NONE,
+        10, // maxRowCount
+        String.join(
+            "\n",
+            "{",
+            "  \"queryType\": \"groupBy\",",
+            "  \"dataSource\": \"test_datasource\",",
+            "  \"granularity\": \"ALL\",",
+            "  \"dimensions\": [\"product\"],",
+            "  \"aggregations\": [",
+            "    {\"type\": \"spectatorHistogram\", \"name\": 
\"merged_histogram\", \"fieldName\": "
+            + "\"histogram\"}",
+            "  ],",
+            "  \"postAggregations\": [",
+            "    {\"type\": \"percentileSpectatorHistogram\", \"name\": 
\"p50\", \"field\": {\"type\": \"fieldAccess\",\"fieldName\": 
\"merged_histogram\"}"
+            + ", \"percentile\": \"50.0\"}",
+            "  ],",
+            "  \"intervals\": 
[\"2016-01-01T00:00:00.000Z/2016-01-31T00:00:00.000Z\"]",
+            "}"
+        )
+    );
+
+    List<ResultRow> results = seq.toList();
+    Assert.assertEquals(6, results.size());
+
+    // First three rows should have valid histograms and percentile values
+    Assert.assertNotNull("Row [0] should have non-null percentile", 
results.get(0).get(2));
+    Assert.assertNotNull("Row [1] should have non-null percentile", 
results.get(1).get(2));
+    Assert.assertNotNull("Row [2] should have non-null percentile", 
results.get(2).get(2));
+
+    // Last three rows have null histograms, so percentile should also be null
+    Assert.assertNull("Row [3] should have null percentile when histogram is 
null", results.get(3).get(2));
+    Assert.assertNull("Row [4] should have null percentile when histogram is 
null", results.get(4).get(2));
+    Assert.assertNull("Row [5] should have null percentile when histogram is 
null", results.get(5).get(2));
+  }
+
+  @Test
+  public void testPercentilesPostAggregatorWithNullSketch() throws Exception
+  {
+    Sequence<ResultRow> seq = helper.createIndexAndRunQueryOnSegment(
+        new 
File(this.getClass().getClassLoader().getResource("input_data.tsv").getFile()),
+        INPUT_DATA_PARSE_SPEC,
+        String.join(
+            "\n",
+            "[",
+            "  {\"type\": \"spectatorHistogram\", \"name\": \"histogram\", 
\"fieldName\": \"cost\"}",
+            "]"
+        ),
+        0, // minTimestamp
+        Granularities.NONE,
+        10, // maxRowCount
+        String.join(
+            "\n",
+            "{",
+            "  \"queryType\": \"groupBy\",",
+            "  \"dataSource\": \"test_datasource\",",
+            "  \"granularity\": \"ALL\",",
+            "  \"dimensions\": [\"product\"],",
+            "  \"aggregations\": [",
+            "    {\"type\": \"spectatorHistogram\", \"name\": 
\"merged_histogram\", \"fieldName\": "
+            + "\"histogram\"}",
+            "  ],",
+            "  \"postAggregations\": [",
+            "    {\"type\": \"percentilesSpectatorHistogram\", \"name\": 
\"percentiles\", \"field\": {\"type\": \"fieldAccess\",\"fieldName\": 
\"merged_histogram\"}"
+            + ", \"percentiles\": [25.0, 50.0, 75.0]}",
+            "  ],",
+            "  \"intervals\": 
[\"2016-01-01T00:00:00.000Z/2016-01-31T00:00:00.000Z\"]",
+            "}"
+        )
+    );
+
+    List<ResultRow> results = seq.toList();
+    Assert.assertEquals(6, results.size());
+
+    // First three rows should have valid histograms and percentiles arrays
+    Assert.assertNotNull("Row [0] should have non-null percentiles array", 
results.get(0).get(2));
+    Assert.assertTrue("Row [0] percentiles should be double array", 
results.get(0).get(2) instanceof double[]);
+    Assert.assertNotNull("Row [1] should have non-null percentiles array", 
results.get(1).get(2));
+    Assert.assertTrue("Row [1] percentiles should be double array", 
results.get(1).get(2) instanceof double[]);
+    Assert.assertNotNull("Row [2] should have non-null percentiles array", 
results.get(2).get(2));
+    Assert.assertTrue("Row [2] percentiles should be double array", 
results.get(2).get(2) instanceof double[]);
+
+    // Last three rows have null histograms, so percentiles should also be null
+    Assert.assertNull("Row [3] should have null percentiles when histogram is 
null", results.get(3).get(2));
+    Assert.assertNull("Row [4] should have null percentiles when histogram is 
null", results.get(4).get(2));
+    Assert.assertNull("Row [5] should have null percentiles when histogram is 
null", results.get(5).get(2));
+  }
+
   private static void assertResultsMatch(List<ResultRow> results, int rowNum, 
String expectedProduct)
   {
     ResultRow row = results.get(rowNum);


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

Reply via email to