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

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


The following commit(s) were added to refs/heads/master by this push:
     new 6b3689c5ef [multistage] support not-in in leaf stage (#9610)
6b3689c5ef is described below

commit 6b3689c5efbedd3c179b06062dfe1f1ab13619cc
Author: Rong Rong <[email protected]>
AuthorDate: Mon Oct 17 19:24:31 2022 -0700

    [multistage] support not-in in leaf stage (#9610)
    
    
    
    Co-authored-by: Rong Rong <[email protected]>
---
 .../common/function/TransformFunctionType.java     |  1 +
 .../transform/function/InTransformFunction.java    | 12 ++---
 .../transform/function/NotInTransformFunction.java | 51 ++++++++++++++++++++++
 .../function/TransformFunctionFactory.java         |  1 +
 .../function/InTransformFunctionTest.java          | 18 ++++++++
 .../java/org/apache/pinot/query/QueryTestSet.java  |  5 +++
 6 files changed, 82 insertions(+), 6 deletions(-)

diff --git 
a/pinot-common/src/main/java/org/apache/pinot/common/function/TransformFunctionType.java
 
b/pinot-common/src/main/java/org/apache/pinot/common/function/TransformFunctionType.java
index f0c28f71ee..3f6ab6a144 100644
--- 
a/pinot-common/src/main/java/org/apache/pinot/common/function/TransformFunctionType.java
+++ 
b/pinot-common/src/main/java/org/apache/pinot/common/function/TransformFunctionType.java
@@ -55,6 +55,7 @@ public enum TransformFunctionType {
   LESS_THAN("less_than"),
   LESS_THAN_OR_EQUAL("less_than_or_equal"),
   IN("in"),
+  NOT_IN("not_in"),
 
   IS_NULL("is_null"),
   IS_NOT_NULL("is_not_null"),
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/InTransformFunction.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/InTransformFunction.java
index 01720358b6..39419cd959 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/InTransformFunction.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/InTransformFunction.java
@@ -57,8 +57,8 @@ public class InTransformFunction extends 
BaseTransformFunction {
   @Override
   public void init(List<TransformFunction> arguments, Map<String, DataSource> 
dataSourceMap) {
     int numArguments = arguments.size();
-    Preconditions.checkArgument(numArguments >= 2,
-        "At least 2 arguments are required for IN transform function: 
expression, values");
+    Preconditions.checkArgument(numArguments >= 2, "At least 2 arguments are 
required for [%s] "
+        + "transform function: (expression, values)", getName());
     _mainFunction = arguments.get(0);
 
     boolean allLiteralValues = true;
@@ -119,13 +119,13 @@ public class InTransformFunction extends 
BaseTransformFunction {
           throw new IllegalStateException();
       }
     } else {
-      
Preconditions.checkArgument(_mainFunction.getResultMetadata().isSingleValue(),
-          "The first argument for IN transform function must be single-valued 
when there are non-literal values");
+      
Preconditions.checkArgument(_mainFunction.getResultMetadata().isSingleValue(), 
"The first argument for [%s] "
+          + "transform function must be single-valued when there are 
non-literal values", getName());
       _valueFunctions = new TransformFunction[numArguments - 1];
       for (int i = 1; i < numArguments; i++) {
         TransformFunction valueFunction = arguments.get(i);
-        
Preconditions.checkArgument(valueFunction.getResultMetadata().isSingleValue(),
-            "The values for IN transform function must be single-valued");
+        
Preconditions.checkArgument(valueFunction.getResultMetadata().isSingleValue(), 
"The values for [%s] "
+                + "transform function must be single-valued", getName());
         _valueFunctions[i - 1] = valueFunction;
       }
     }
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/NotInTransformFunction.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/NotInTransformFunction.java
new file mode 100644
index 0000000000..dd09574847
--- /dev/null
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/NotInTransformFunction.java
@@ -0,0 +1,51 @@
+/**
+ * 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.pinot.core.operator.transform.function;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.pinot.common.function.TransformFunctionType;
+import org.apache.pinot.core.operator.blocks.ProjectionBlock;
+import org.apache.pinot.segment.spi.datasource.DataSource;
+
+
+/**
+ * The NOT_IN transform function is the negate version of the {@link 
InTransformFunction}.
+ */
+public class NotInTransformFunction extends InTransformFunction {
+
+  @Override
+  public String getName() {
+    return TransformFunctionType.NOT_IN.getName();
+  }
+
+  @Override
+  public void init(List<TransformFunction> arguments, Map<String, DataSource> 
dataSourceMap) {
+    super.init(arguments, dataSourceMap);
+  }
+
+  @Override
+  public int[] transformToIntValuesSV(ProjectionBlock projectionBlock) {
+    int[] intValuesSV = super.transformToIntValuesSV(projectionBlock);
+    for (int i = 0; i < intValuesSV.length; i++) {
+      intValuesSV[i] = 1 - intValuesSV[i];
+    }
+    return intValuesSV;
+  }
+}
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/TransformFunctionFactory.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/TransformFunctionFactory.java
index 74a2763345..043c23cf19 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/TransformFunctionFactory.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/TransformFunctionFactory.java
@@ -157,6 +157,7 @@ public class TransformFunctionFactory {
     typeToImplementation.put(TransformFunctionType.LESS_THAN_OR_EQUAL,
         LessThanOrEqualTransformFunction.class);
     typeToImplementation.put(TransformFunctionType.IN, 
InTransformFunction.class);
+    typeToImplementation.put(TransformFunctionType.NOT_IN, 
NotInTransformFunction.class);
 
     // logical functions
     typeToImplementation.put(TransformFunctionType.AND, 
AndOperatorTransformFunction.class);
diff --git 
a/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/InTransformFunctionTest.java
 
b/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/InTransformFunctionTest.java
index 70f0864ffb..950c8da400 100644
--- 
a/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/InTransformFunctionTest.java
+++ 
b/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/InTransformFunctionTest.java
@@ -51,6 +51,24 @@ public class InTransformFunctionTest extends 
BaseTransformFunctionTest {
       assertEquals(intValues[i], inValues.contains(_intSVValues[i]) ? 1 : 0);
     }
   }
+  @Test
+  public void testIntNotInTransformFunction() {
+    String expressionStr =
+        String.format("%s NOT IN (%d, %d, %d)", INT_SV_COLUMN, 
_intSVValues[2], _intSVValues[5], _intSVValues[9]);
+    ExpressionContext expression = 
RequestContextUtils.getExpression(expressionStr);
+    TransformFunction transformFunction = 
TransformFunctionFactory.get(expression, _dataSourceMap);
+    assertTrue(transformFunction instanceof InTransformFunction);
+    assertEquals(transformFunction.getName(), 
TransformFunctionType.NOT_IN.getName());
+
+    Set<Integer> inValues = Sets.newHashSet(_intSVValues[2], _intSVValues[5], 
_intSVValues[9]);
+    int[] intValues = 
transformFunction.transformToIntValuesSV(_projectionBlock);
+    for (int i = 0; i < NUM_ROWS; i++) {
+      if (i != 2 && i != 5 && i != 9) {
+        assertEquals(intValues[i], 1);
+      }
+      assertEquals(intValues[i], inValues.contains(_intSVValues[i]) ? 0 : 1);
+    }
+  }
 
   @Test
   public void testIntMVInTransformFunction() {
diff --git 
a/pinot-query-runtime/src/test/java/org/apache/pinot/query/QueryTestSet.java 
b/pinot-query-runtime/src/test/java/org/apache/pinot/query/QueryTestSet.java
index 0456872a38..12adcd7e5c 100644
--- a/pinot-query-runtime/src/test/java/org/apache/pinot/query/QueryTestSet.java
+++ b/pinot-query-runtime/src/test/java/org/apache/pinot/query/QueryTestSet.java
@@ -95,6 +95,11 @@ public class QueryTestSet {
             + " WHERE a.col1 IN ('foo') AND b.col2 NOT IN ('')"},
 
         // Range conditions with continuous and non-continuous range.
+        // Calcite default compilation will convert multiple `=` and `<>` into 
range IN and NOT IN search predicates.
+        new Object[]{"SELECT a.col1, SUM(CASE WHEN a.col2 = 'foo' OR a.col2 = 
'alice' THEN 1 ELSE 0 END) AS match_sum, "
+            + " SUM(CASE WHEN a.col2 <> 'foo' AND a.col2 <> 'alice' THEN 1 
ELSE 0 END) as unmatch_sum "
+            + " FROM a WHERE a.ts >= 1600000000 GROUP BY a.col1"},
+
         new Object[]{"SELECT a.col1, b.col2 FROM a JOIN b ON a.col1 = b.col1 "
             + " WHERE a.col3 IN (1, 2, 3) OR (a.col3 > 10 AND a.col3 < 50)"},
 


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

Reply via email to