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

asdf2014 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 3f4d66c3997 Check for Unsupported Aggregation with Distinct when 
useApproxCountDistinct is enabled (#16770)
3f4d66c3997 is described below

commit 3f4d66c3997619e96e52af90d82b9a5b96660a84
Author: Sree Charan Manamala <[email protected]>
AuthorDate: Wed Jul 24 08:43:22 2024 +0530

    Check for Unsupported Aggregation with Distinct when useApproxCountDistinct 
is enabled (#16770)
    
    * init
    
    * add NativelySupportsDistinct
    
    * refactor
    
    * javadoc
    
    * refactor
    
    * fix tests
    
    * fix drill tests
    
    * comments
    
    * Update 
sql/src/test/java/org/apache/druid/sql/calcite/DrillWindowQueryTest.java
    
    ---------
    
    Co-authored-by: Benedict Jin <[email protected]>
---
 .../ApproxCountDistinctSqlAggregator.java          |  1 +
 .../aggregation/NativelySupportsDistinct.java      | 36 ++++++++++++++++++++++
 .../builtin/ArrayConcatSqlAggregator.java          |  2 ++
 .../aggregation/builtin/ArraySqlAggregator.java    |  2 ++
 .../aggregation/builtin/StringSqlAggregator.java   |  2 ++
 .../sql/calcite/planner/DruidSqlValidator.java     | 21 +++++++++++--
 .../druid/sql/calcite/rule/GroupByRules.java       | 12 ++++++++
 .../apache/druid/sql/calcite/CalciteQueryTest.java | 14 +++++++++
 .../druid/sql/calcite/DrillWindowQueryTest.java    |  4 +--
 .../apache/druid/sql/calcite/NotYetSupported.java  |  2 +-
 10 files changed, 91 insertions(+), 5 deletions(-)

diff --git 
a/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/ApproxCountDistinctSqlAggregator.java
 
b/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/ApproxCountDistinctSqlAggregator.java
index a8bae969863..7d66eebcad1 100644
--- 
a/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/ApproxCountDistinctSqlAggregator.java
+++ 
b/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/ApproxCountDistinctSqlAggregator.java
@@ -80,6 +80,7 @@ public class ApproxCountDistinctSqlAggregator implements 
SqlAggregator
     );
   }
 
+  @NativelySupportsDistinct
   private static class ApproxCountDistinctSqlAggFunction extends SqlAggFunction
   {
     ApproxCountDistinctSqlAggFunction(SqlAggFunction delegate)
diff --git 
a/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/NativelySupportsDistinct.java
 
b/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/NativelySupportsDistinct.java
new file mode 100644
index 00000000000..19bbaf8a0f2
--- /dev/null
+++ 
b/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/NativelySupportsDistinct.java
@@ -0,0 +1,36 @@
+/*
+ * 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.druid.sql.calcite.aggregation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation is to distinguish {@link 
org.apache.calcite.sql.SqlAggFunction}
+ * which supports the distinct aggregation natively
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface NativelySupportsDistinct
+{
+
+}
diff --git 
a/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/builtin/ArrayConcatSqlAggregator.java
 
b/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/builtin/ArrayConcatSqlAggregator.java
index a5e62f5e2a9..d20999d3afc 100644
--- 
a/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/builtin/ArrayConcatSqlAggregator.java
+++ 
b/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/builtin/ArrayConcatSqlAggregator.java
@@ -39,6 +39,7 @@ import 
org.apache.druid.query.aggregation.ExpressionLambdaAggregatorFactory;
 import org.apache.druid.segment.VirtualColumn;
 import org.apache.druid.segment.column.ColumnType;
 import org.apache.druid.sql.calcite.aggregation.Aggregation;
+import org.apache.druid.sql.calcite.aggregation.NativelySupportsDistinct;
 import org.apache.druid.sql.calcite.aggregation.SqlAggregator;
 import org.apache.druid.sql.calcite.expression.DruidExpression;
 import org.apache.druid.sql.calcite.expression.Expressions;
@@ -142,6 +143,7 @@ public class ArrayConcatSqlAggregator implements 
SqlAggregator
     }
   }
 
+  @NativelySupportsDistinct
   private static class ArrayConcatAggFunction extends SqlAggFunction
   {
     ArrayConcatAggFunction()
diff --git 
a/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/builtin/ArraySqlAggregator.java
 
b/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/builtin/ArraySqlAggregator.java
index efb84dca625..1045a79870b 100644
--- 
a/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/builtin/ArraySqlAggregator.java
+++ 
b/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/builtin/ArraySqlAggregator.java
@@ -41,6 +41,7 @@ import org.apache.druid.math.expr.ExpressionType;
 import org.apache.druid.query.aggregation.ExpressionLambdaAggregatorFactory;
 import org.apache.druid.segment.column.ColumnType;
 import org.apache.druid.sql.calcite.aggregation.Aggregation;
+import org.apache.druid.sql.calcite.aggregation.NativelySupportsDistinct;
 import org.apache.druid.sql.calcite.aggregation.SqlAggregator;
 import org.apache.druid.sql.calcite.expression.DruidExpression;
 import org.apache.druid.sql.calcite.expression.Expressions;
@@ -165,6 +166,7 @@ public class ArraySqlAggregator implements SqlAggregator
     }
   }
 
+  @NativelySupportsDistinct
   private static class ArrayAggFunction extends SqlAggFunction
   {
     private static final ArrayAggReturnTypeInference RETURN_TYPE_INFERENCE = 
new ArrayAggReturnTypeInference();
diff --git 
a/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/builtin/StringSqlAggregator.java
 
b/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/builtin/StringSqlAggregator.java
index a78b3a7a479..49469decf99 100644
--- 
a/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/builtin/StringSqlAggregator.java
+++ 
b/sql/src/main/java/org/apache/druid/sql/calcite/aggregation/builtin/StringSqlAggregator.java
@@ -47,6 +47,7 @@ import org.apache.druid.query.filter.NullFilter;
 import org.apache.druid.query.filter.SelectorDimFilter;
 import org.apache.druid.segment.column.ColumnType;
 import org.apache.druid.sql.calcite.aggregation.Aggregation;
+import org.apache.druid.sql.calcite.aggregation.NativelySupportsDistinct;
 import org.apache.druid.sql.calcite.aggregation.SqlAggregator;
 import org.apache.druid.sql.calcite.expression.DruidExpression;
 import org.apache.druid.sql.calcite.expression.Expressions;
@@ -226,6 +227,7 @@ public class StringSqlAggregator implements SqlAggregator
     }
   }
 
+  @NativelySupportsDistinct
   private static class StringAggFunction extends SqlAggFunction
   {
     private static final StringAggReturnTypeInference RETURN_TYPE_INFERENCE = 
new StringAggReturnTypeInference();
diff --git 
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidSqlValidator.java 
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidSqlValidator.java
index 18638b32afd..e00a2915a2e 100644
--- 
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidSqlValidator.java
+++ 
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidSqlValidator.java
@@ -28,6 +28,7 @@ import org.apache.calcite.rel.type.RelDataTypeField;
 import org.apache.calcite.rel.type.RelRecordType;
 import org.apache.calcite.runtime.CalciteContextException;
 import org.apache.calcite.runtime.CalciteException;
+import org.apache.calcite.sql.SqlAggFunction;
 import org.apache.calcite.sql.SqlCall;
 import org.apache.calcite.sql.SqlIdentifier;
 import org.apache.calcite.sql.SqlInsert;
@@ -65,6 +66,7 @@ import org.apache.druid.query.QueryContext;
 import org.apache.druid.segment.column.ColumnType;
 import org.apache.druid.segment.column.Types;
 import org.apache.druid.segment.column.ValueType;
+import org.apache.druid.sql.calcite.aggregation.NativelySupportsDistinct;
 import 
org.apache.druid.sql.calcite.expression.builtin.ScalarInArrayOperatorConversion;
 import org.apache.druid.sql.calcite.parser.DruidSqlIngest;
 import org.apache.druid.sql.calcite.parser.DruidSqlInsert;
@@ -760,8 +762,10 @@ public class DruidSqlValidator extends 
BaseDruidSqlValidator
         throw buildCalciteContextException(
             StringUtils.format(
                 "The query contains window functions; To run these window 
functions, specify [%s] in query context.",
-                PlannerContext.CTX_ENABLE_WINDOW_FNS),
-            call);
+                PlannerContext.CTX_ENABLE_WINDOW_FNS
+            ),
+            call
+        );
       }
     }
     if (call.getKind() == SqlKind.NULLS_FIRST) {
@@ -776,6 +780,19 @@ public class DruidSqlValidator extends 
BaseDruidSqlValidator
         throw buildCalciteContextException("ASCENDING ordering with NULLS LAST 
is not supported!", call);
       }
     }
+    if (plannerContext.getPlannerConfig().isUseApproximateCountDistinct() && 
isSqlCallDistinct(call)) {
+      if (call.getOperator().getKind() != SqlKind.COUNT && call.getOperator() 
instanceof SqlAggFunction) {
+        if 
(!call.getOperator().getClass().isAnnotationPresent(NativelySupportsDistinct.class))
 {
+          throw buildCalciteContextException(
+              StringUtils.format(
+                  "Aggregation [%s] with DISTINCT is not supported when 
useApproximateCountDistinct is enabled. Run with disabling it.",
+                  call.getOperator().getName()
+              ),
+              call
+          );
+        }
+      }
+    }
     super.validateCall(call, scope);
   }
 
diff --git 
a/sql/src/main/java/org/apache/druid/sql/calcite/rule/GroupByRules.java 
b/sql/src/main/java/org/apache/druid/sql/calcite/rule/GroupByRules.java
index fecabd00ec3..f0632006d10 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/rule/GroupByRules.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/rule/GroupByRules.java
@@ -22,11 +22,13 @@ package org.apache.druid.sql.calcite.rule;
 import org.apache.calcite.rel.core.AggregateCall;
 import org.apache.calcite.rex.RexBuilder;
 import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.sql.SqlKind;
 import org.apache.druid.query.aggregation.AggregatorFactory;
 import org.apache.druid.query.aggregation.FilteredAggregatorFactory;
 import org.apache.druid.query.filter.DimFilter;
 import org.apache.druid.segment.column.RowSignature;
 import org.apache.druid.sql.calcite.aggregation.Aggregation;
+import org.apache.druid.sql.calcite.aggregation.NativelySupportsDistinct;
 import org.apache.druid.sql.calcite.aggregation.SqlAggregator;
 import org.apache.druid.sql.calcite.expression.Expressions;
 import org.apache.druid.sql.calcite.filtration.Filtration;
@@ -69,6 +71,16 @@ public class GroupByRules
       return null;
     }
 
+    if (call.isDistinct() && call.getAggregation().getKind() != SqlKind.COUNT) 
{
+      if 
(!call.getAggregation().getClass().isAnnotationPresent(NativelySupportsDistinct.class))
 {
+        plannerContext.setPlanningError(
+            "Aggregation [%s] with DISTINCT is not supported when 
useApproximateCountDistinct is enabled. Run with disabling it.",
+            call.getAggregation().getName()
+        );
+        return null;
+      }
+    }
+
     final DimFilter filter;
 
     if (call.filterArg >= 0) {
diff --git 
a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java 
b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java
index 29751279339..7b5749bd8a1 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java
@@ -15501,6 +15501,20 @@ public class CalciteQueryTest extends 
BaseCalciteQueryTest
     assertThat(e, invalidSqlIs("The query contains window functions; To run 
these window functions, specify [enableWindowing] in query context. (line [1], 
column [13])"));
   }
 
+  @Test
+  public void testDistinctSumNotSupportedWithApproximation()
+  {
+    DruidException e = assertThrows(
+        DruidException.class,
+        () -> testBuilder()
+            
.queryContext(ImmutableMap.of(PlannerConfig.CTX_KEY_USE_APPROXIMATE_COUNT_DISTINCT,
 true))
+            .sql("SELECT sum(distinct m1) from druid.foo")
+            .run()
+    );
+
+    assertThat(e, invalidSqlContains("Aggregation [SUM] with DISTINCT is not 
supported"));
+  }
+
   @Test
   public void testUnSupportedNullsFirst()
   {
diff --git 
a/sql/src/test/java/org/apache/druid/sql/calcite/DrillWindowQueryTest.java 
b/sql/src/test/java/org/apache/druid/sql/calcite/DrillWindowQueryTest.java
index 24076d1cdbf..1451d2495c9 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/DrillWindowQueryTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/DrillWindowQueryTest.java
@@ -4426,7 +4426,7 @@ public class DrillWindowQueryTest extends 
BaseCalciteQueryTest
     windowQueryTest();
   }
 
-  @NotYetSupported(Modes.NOT_ENOUGH_RULES)
+  @NotYetSupported(Modes.DISTINCT_AGGREGATE_NOT_SUPPORTED)
   @DrillTest("nestedAggs/emtyOvrCls_7")
   @Test
   public void test_nestedAggs_emtyOvrCls_7()
@@ -7274,7 +7274,7 @@ public class DrillWindowQueryTest extends 
BaseCalciteQueryTest
     windowQueryTest();
   }
 
-  @NotYetSupported(Modes.RESULT_MISMATCH)
+  @NotYetSupported(Modes.DISTINCT_AGGREGATE_NOT_SUPPORTED)
   @DrillTest("nestedAggs/emtyOvrCls_8")
   @Test
   public void test_nestedAggs_emtyOvrCls_8()
diff --git 
a/sql/src/test/java/org/apache/druid/sql/calcite/NotYetSupported.java 
b/sql/src/test/java/org/apache/druid/sql/calcite/NotYetSupported.java
index eaa97be231f..e5442a2bda2 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/NotYetSupported.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/NotYetSupported.java
@@ -77,7 +77,7 @@ public @interface NotYetSupported
   enum Modes
   {
     // @formatter:off
-    NOT_ENOUGH_RULES(DruidException.class, "not enough rules"),
+    DISTINCT_AGGREGATE_NOT_SUPPORTED(DruidException.class, "DISTINCT is not 
supported"),
     ERROR_HANDLING(AssertionError.class, "targetPersona: is <[A-Z]+> and 
category: is <[A-Z_]+> and errorCode: is"),
     EXPRESSION_NOT_GROUPED(DruidException.class, "Expression '[a-z]+' is not 
being grouped"),
     NULLS_FIRST_LAST(DruidException.class, "NULLS (FIRST|LAST)"),


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

Reply via email to