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

jackie 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 e01df9a7ce Data visitors (#10361)
e01df9a7ce is described below

commit e01df9a7ce4867aaf663ec5f6ba5b3df41a61ea4
Author: Gonzalo Ortiz Jaureguizar <[email protected]>
AuthorDate: Thu Mar 16 21:51:28 2023 +0100

    Data visitors (#10361)
---
 .../predicate/EqualsPredicateEvaluatorFactory.java |  78 ++++++++++++--
 .../predicate/InPredicateEvaluatorFactory.java     |  67 ++++++++++--
 .../NotEqualsPredicateEvaluatorFactory.java        |  72 +++++++++++--
 .../predicate/NotInPredicateEvaluatorFactory.java  |  68 ++++++++++--
 .../predicate/InPredicateEvaluatorFactoryTest.java | 115 +++++++++++++++++++++
 .../apache/pinot/spi/data/MultiValueVisitor.java   |  99 ++++++++++++++++++
 .../apache/pinot/spi/data/SingleValueVisitor.java  |  45 ++++++++
 7 files changed, 510 insertions(+), 34 deletions(-)

diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/EqualsPredicateEvaluatorFactory.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/EqualsPredicateEvaluatorFactory.java
index dcc3f34f65..14616b36be 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/EqualsPredicateEvaluatorFactory.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/EqualsPredicateEvaluatorFactory.java
@@ -21,12 +21,15 @@ package org.apache.pinot.core.operator.filter.predicate;
 import java.math.BigDecimal;
 import java.util.Arrays;
 import org.apache.pinot.common.request.context.predicate.EqPredicate;
+import org.apache.pinot.common.request.context.predicate.Predicate;
 import org.apache.pinot.core.operator.filter.predicate.traits.DoubleValue;
 import org.apache.pinot.core.operator.filter.predicate.traits.FloatValue;
 import org.apache.pinot.core.operator.filter.predicate.traits.IntValue;
 import org.apache.pinot.core.operator.filter.predicate.traits.LongValue;
 import org.apache.pinot.segment.spi.index.reader.Dictionary;
 import org.apache.pinot.spi.data.FieldSpec.DataType;
+import org.apache.pinot.spi.data.MultiValueVisitor;
+import org.apache.pinot.spi.data.SingleValueVisitor;
 import org.apache.pinot.spi.utils.BooleanUtils;
 import org.apache.pinot.spi.utils.BytesUtils;
 import org.apache.pinot.spi.utils.TimestampUtils;
@@ -59,7 +62,7 @@ public class EqualsPredicateEvaluatorFactory {
    * @param dataType Data type for the column
    * @return Raw value based EQ predicate evaluator
    */
-  public static BaseRawValueBasedPredicateEvaluator 
newRawValueBasedEvaluator(EqPredicate eqPredicate,
+  public static EqRawPredicateEvaluator newRawValueBasedEvaluator(EqPredicate 
eqPredicate,
       DataType dataType) {
     String value = eqPredicate.getValue();
     switch (dataType) {
@@ -140,8 +143,25 @@ public class EqualsPredicateEvaluatorFactory {
     }
   }
 
-  private static final class IntRawValueBasedEqPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator
-      implements IntValue {
+  public static abstract class EqRawPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+    public EqRawPredicateEvaluator(Predicate predicate) {
+      super(predicate);
+    }
+
+    /**
+     * Visits the matching value of this predicate.
+     */
+    public abstract <R> R accept(SingleValueVisitor<R> visitor);
+
+    /**
+     * Visits the matching value of this predicate, which will be transformed 
into an array with a single value.
+     */
+    public <R> R accept(MultiValueVisitor<R> visitor) {
+      return accept(visitor.asSingleValueVisitor());
+    }
+  }
+
+  private static final class IntRawValueBasedEqPredicateEvaluator extends 
EqRawPredicateEvaluator implements IntValue {
     final int _matchingValue;
 
     IntRawValueBasedEqPredicateEvaluator(EqPredicate eqPredicate, int 
matchingValue) {
@@ -149,6 +169,11 @@ public class EqualsPredicateEvaluatorFactory {
       _matchingValue = matchingValue;
     }
 
+    @Override
+    public <R> R accept(SingleValueVisitor<R> visitor) {
+      return visitor.visitInt(_matchingValue);
+    }
+
     @Override
     public int getNumMatchingItems() {
       return 1;
@@ -183,7 +208,7 @@ public class EqualsPredicateEvaluatorFactory {
     }
   }
 
-  private static final class LongRawValueBasedEqPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator
+  private static final class LongRawValueBasedEqPredicateEvaluator extends 
EqRawPredicateEvaluator
       implements LongValue {
     final long _matchingValue;
 
@@ -192,6 +217,16 @@ public class EqualsPredicateEvaluatorFactory {
       _matchingValue = matchingValue;
     }
 
+    @Override
+    public <R> R accept(SingleValueVisitor<R> visitor) {
+      return visitor.visitLong(_matchingValue);
+    }
+
+    @Override
+    public <R> R accept(MultiValueVisitor<R> visitor) {
+      return visitor.asSingleValueVisitor().visitLong(_matchingValue);
+    }
+
     @Override
     public int getNumMatchingItems() {
       return 1;
@@ -226,7 +261,7 @@ public class EqualsPredicateEvaluatorFactory {
     }
   }
 
-  private static final class FloatRawValueBasedEqPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator
+  private static final class FloatRawValueBasedEqPredicateEvaluator extends 
EqRawPredicateEvaluator
       implements FloatValue {
     final float _matchingValue;
 
@@ -235,6 +270,11 @@ public class EqualsPredicateEvaluatorFactory {
       _matchingValue = matchingValue;
     }
 
+    @Override
+    public <R> R accept(SingleValueVisitor<R> visitor) {
+      return visitor.visitFloat(_matchingValue);
+    }
+
     @Override
     public int getNumMatchingItems() {
       return 1;
@@ -269,7 +309,7 @@ public class EqualsPredicateEvaluatorFactory {
     }
   }
 
-  private static final class DoubleRawValueBasedEqPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator
+  private static final class DoubleRawValueBasedEqPredicateEvaluator extends 
EqRawPredicateEvaluator
       implements DoubleValue {
     final double _matchingValue;
 
@@ -278,6 +318,11 @@ public class EqualsPredicateEvaluatorFactory {
       _matchingValue = matchingValue;
     }
 
+    @Override
+    public <R> R accept(SingleValueVisitor<R> visitor) {
+      return visitor.visitDouble(_matchingValue);
+    }
+
     @Override
     public int getNumMatchingItems() {
       return 1;
@@ -312,7 +357,7 @@ public class EqualsPredicateEvaluatorFactory {
     }
   }
 
-  private static final class BigDecimalRawValueBasedEqPredicateEvaluator 
extends BaseRawValueBasedPredicateEvaluator {
+  private static final class BigDecimalRawValueBasedEqPredicateEvaluator 
extends EqRawPredicateEvaluator {
     final BigDecimal _matchingValue;
 
     BigDecimalRawValueBasedEqPredicateEvaluator(EqPredicate eqPredicate, 
BigDecimal matchingValue) {
@@ -320,6 +365,11 @@ public class EqualsPredicateEvaluatorFactory {
       _matchingValue = matchingValue;
     }
 
+    @Override
+    public <R> R accept(SingleValueVisitor<R> visitor) {
+      return visitor.visitBigDecimal(_matchingValue);
+    }
+
     @Override
     public int getNumMatchingItems() {
       return 1;
@@ -336,7 +386,7 @@ public class EqualsPredicateEvaluatorFactory {
     }
   }
 
-  private static final class StringRawValueBasedEqPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+  private static final class StringRawValueBasedEqPredicateEvaluator extends 
EqRawPredicateEvaluator {
     final String _matchingValue;
 
     StringRawValueBasedEqPredicateEvaluator(EqPredicate eqPredicate, String 
matchingValue) {
@@ -344,6 +394,11 @@ public class EqualsPredicateEvaluatorFactory {
       _matchingValue = matchingValue;
     }
 
+    @Override
+    public <R> R accept(SingleValueVisitor<R> visitor) {
+      return visitor.visitString(_matchingValue);
+    }
+
     @Override
     public int getNumMatchingItems() {
       return 1;
@@ -360,7 +415,7 @@ public class EqualsPredicateEvaluatorFactory {
     }
   }
 
-  private static final class BytesRawValueBasedEqPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+  private static final class BytesRawValueBasedEqPredicateEvaluator extends 
EqRawPredicateEvaluator {
     final byte[] _matchingValue;
 
     BytesRawValueBasedEqPredicateEvaluator(EqPredicate eqPredicate, byte[] 
matchingValue) {
@@ -368,6 +423,11 @@ public class EqualsPredicateEvaluatorFactory {
       _matchingValue = matchingValue;
     }
 
+    @Override
+    public <R> R accept(SingleValueVisitor<R> visitor) {
+      return visitor.visitBytes(_matchingValue);
+    }
+
     @Override
     public int getNumMatchingItems() {
       return 1;
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/InPredicateEvaluatorFactory.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/InPredicateEvaluatorFactory.java
index 9bbebcec57..9ad0a78014 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/InPredicateEvaluatorFactory.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/InPredicateEvaluatorFactory.java
@@ -34,10 +34,12 @@ import java.util.Set;
 import java.util.TreeSet;
 import javax.annotation.Nullable;
 import org.apache.pinot.common.request.context.predicate.InPredicate;
+import org.apache.pinot.common.request.context.predicate.Predicate;
 import org.apache.pinot.common.utils.HashUtil;
 import org.apache.pinot.core.query.request.context.QueryContext;
 import org.apache.pinot.segment.spi.index.reader.Dictionary;
 import org.apache.pinot.spi.data.FieldSpec.DataType;
+import org.apache.pinot.spi.data.MultiValueVisitor;
 import org.apache.pinot.spi.utils.ByteArray;
 
 
@@ -69,7 +71,7 @@ public class InPredicateEvaluatorFactory {
    * @param dataType Data type for the column
    * @return Raw value based IN predicate evaluator
    */
-  public static BaseRawValueBasedPredicateEvaluator 
newRawValueBasedEvaluator(InPredicate inPredicate,
+  public static InRawPredicateEvaluator newRawValueBasedEvaluator(InPredicate 
inPredicate,
       DataType dataType) {
     switch (dataType) {
       case INT: {
@@ -207,7 +209,18 @@ public class InPredicateEvaluatorFactory {
     }
   }
 
-  private static final class IntRawValueBasedInPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+  public static abstract class InRawPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+    public InRawPredicateEvaluator(Predicate predicate) {
+      super(predicate);
+    }
+
+    /**
+     * Visits the matching value of this predicate.
+     */
+    public abstract <R> R accept(MultiValueVisitor<R> visitor);
+  }
+
+  private static final class IntRawValueBasedInPredicateEvaluator extends 
InRawPredicateEvaluator {
     final IntSet _matchingValues;
 
     IntRawValueBasedInPredicateEvaluator(InPredicate inPredicate, IntSet 
matchingValues) {
@@ -242,9 +255,14 @@ public class InPredicateEvaluatorFactory {
       }
       return matches;
     }
+
+    @Override
+    public <R> R accept(MultiValueVisitor<R> visitor) {
+      return visitor.visitInt(_matchingValues.toIntArray());
+    }
   }
 
-  private static final class LongRawValueBasedInPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+  private static final class LongRawValueBasedInPredicateEvaluator extends 
InRawPredicateEvaluator {
     final LongSet _matchingValues;
 
     LongRawValueBasedInPredicateEvaluator(InPredicate inPredicate, LongSet 
matchingValues) {
@@ -279,9 +297,14 @@ public class InPredicateEvaluatorFactory {
       }
       return matches;
     }
+
+    @Override
+    public <R> R accept(MultiValueVisitor<R> visitor) {
+      return visitor.visitLong(_matchingValues.toLongArray());
+    }
   }
 
-  private static final class FloatRawValueBasedInPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+  private static final class FloatRawValueBasedInPredicateEvaluator extends 
InRawPredicateEvaluator {
     final FloatSet _matchingValues;
 
     FloatRawValueBasedInPredicateEvaluator(InPredicate inPredicate, FloatSet 
matchingValues) {
@@ -316,9 +339,14 @@ public class InPredicateEvaluatorFactory {
       }
       return matches;
     }
+
+    @Override
+    public <R> R accept(MultiValueVisitor<R> visitor) {
+      return visitor.visitFloat(_matchingValues.toFloatArray());
+    }
   }
 
-  private static final class DoubleRawValueBasedInPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+  private static final class DoubleRawValueBasedInPredicateEvaluator extends 
InRawPredicateEvaluator {
     final DoubleSet _matchingValues;
 
     DoubleRawValueBasedInPredicateEvaluator(InPredicate inPredicate, DoubleSet 
matchingValues) {
@@ -353,9 +381,14 @@ public class InPredicateEvaluatorFactory {
       }
       return matches;
     }
+
+    @Override
+    public <R> R accept(MultiValueVisitor<R> visitor) {
+      return visitor.visitDouble(_matchingValues.toDoubleArray());
+    }
   }
 
-  private static final class BigDecimalRawValueBasedInPredicateEvaluator 
extends BaseRawValueBasedPredicateEvaluator {
+  private static final class BigDecimalRawValueBasedInPredicateEvaluator 
extends InRawPredicateEvaluator {
     // Note: BigDecimal's compareTo is not consistent with equals (e.g. 
compareTo(3.0, 3) returns zero when
     //   equals(3.0, 3) returns false).
     // - HashSet implementation consider both hashCode() and equals() for the 
key.
@@ -383,9 +416,14 @@ public class InPredicateEvaluatorFactory {
     public boolean applySV(BigDecimal value) {
       return _matchingValues.contains(value);
     }
+
+    @Override
+    public <R> R accept(MultiValueVisitor<R> visitor) {
+      return visitor.visitBigDecimal(_matchingValues.toArray(new 
BigDecimal[0]));
+    }
   }
 
-  private static final class StringRawValueBasedInPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+  private static final class StringRawValueBasedInPredicateEvaluator extends 
InRawPredicateEvaluator {
     final Set<String> _matchingValues;
 
     StringRawValueBasedInPredicateEvaluator(InPredicate inPredicate, 
Set<String> matchingValues) {
@@ -407,9 +445,14 @@ public class InPredicateEvaluatorFactory {
     public boolean applySV(String value) {
       return _matchingValues.contains(value);
     }
+
+    @Override
+    public <R> R accept(MultiValueVisitor<R> visitor) {
+      return visitor.visitString(_matchingValues.toArray(new String[0]));
+    }
   }
 
-  private static final class BytesRawValueBasedInPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+  private static final class BytesRawValueBasedInPredicateEvaluator extends 
InRawPredicateEvaluator {
     final Set<ByteArray> _matchingValues;
 
     BytesRawValueBasedInPredicateEvaluator(InPredicate inPredicate, 
Set<ByteArray> matchingValues) {
@@ -431,5 +474,13 @@ public class InPredicateEvaluatorFactory {
     public boolean applySV(byte[] value) {
       return _matchingValues.contains(new ByteArray(value));
     }
+
+    @Override
+    public <R> R accept(MultiValueVisitor<R> visitor) {
+      byte[][] bytes = _matchingValues.stream()
+          .map(ByteArray::getBytes)
+          .toArray(byte[][]::new);
+      return visitor.visitBytes(bytes);
+    }
   }
 }
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/NotEqualsPredicateEvaluatorFactory.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/NotEqualsPredicateEvaluatorFactory.java
index f091039f1d..54ce7df58c 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/NotEqualsPredicateEvaluatorFactory.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/NotEqualsPredicateEvaluatorFactory.java
@@ -21,8 +21,11 @@ package org.apache.pinot.core.operator.filter.predicate;
 import java.math.BigDecimal;
 import java.util.Arrays;
 import org.apache.pinot.common.request.context.predicate.NotEqPredicate;
+import org.apache.pinot.common.request.context.predicate.Predicate;
 import org.apache.pinot.segment.spi.index.reader.Dictionary;
 import org.apache.pinot.spi.data.FieldSpec.DataType;
+import org.apache.pinot.spi.data.MultiValueVisitor;
+import org.apache.pinot.spi.data.SingleValueVisitor;
 import org.apache.pinot.spi.utils.BooleanUtils;
 import org.apache.pinot.spi.utils.BytesUtils;
 import org.apache.pinot.spi.utils.TimestampUtils;
@@ -55,7 +58,7 @@ public class NotEqualsPredicateEvaluatorFactory {
    * @param dataType Data type for the column
    * @return Raw value based NOT_EQ predicate evaluator
    */
-  public static BaseRawValueBasedPredicateEvaluator 
newRawValueBasedEvaluator(NotEqPredicate notEqPredicate,
+  public static NeqRawPredicateEvaluator 
newRawValueBasedEvaluator(NotEqPredicate notEqPredicate,
       DataType dataType) {
     String value = notEqPredicate.getValue();
     switch (dataType) {
@@ -155,7 +158,25 @@ public class NotEqualsPredicateEvaluatorFactory {
     }
   }
 
-  private static final class IntRawValueBasedNeqPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+  public static abstract class NeqRawPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+    public NeqRawPredicateEvaluator(Predicate predicate) {
+      super(predicate);
+    }
+
+    /**
+     * Visits the not matching value of this predicate.
+     */
+    public abstract <R> R accept(SingleValueVisitor<R> visitor);
+
+    /**
+     * Visits the not matching value of this predicate, which will be 
transformed into an array with a single value.
+     */
+    public <R> R accept(MultiValueVisitor<R> visitor) {
+      return accept(visitor.asSingleValueVisitor());
+    }
+  }
+
+  private static final class IntRawValueBasedNeqPredicateEvaluator extends 
NeqRawPredicateEvaluator {
     final int _nonMatchingValue;
 
     IntRawValueBasedNeqPredicateEvaluator(NotEqPredicate notEqPredicate, int 
nonMatchingValue) {
@@ -190,9 +211,14 @@ public class NotEqualsPredicateEvaluatorFactory {
       }
       return matches;
     }
+
+    @Override
+    public <R> R accept(SingleValueVisitor<R> visitor) {
+      return visitor.visitInt(_nonMatchingValue);
+    }
   }
 
-  private static final class LongRawValueBasedNeqPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+  private static final class LongRawValueBasedNeqPredicateEvaluator extends 
NeqRawPredicateEvaluator {
     final long _nonMatchingValue;
 
     LongRawValueBasedNeqPredicateEvaluator(NotEqPredicate notEqPredicate, long 
nonMatchingValue) {
@@ -227,9 +253,14 @@ public class NotEqualsPredicateEvaluatorFactory {
       }
       return matches;
     }
+
+    @Override
+    public <R> R accept(SingleValueVisitor<R> visitor) {
+      return visitor.visitLong(_nonMatchingValue);
+    }
   }
 
-  private static final class FloatRawValueBasedNeqPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+  private static final class FloatRawValueBasedNeqPredicateEvaluator extends 
NeqRawPredicateEvaluator {
     final float _nonMatchingValue;
 
     FloatRawValueBasedNeqPredicateEvaluator(NotEqPredicate notEqPredicate, 
float nonMatchingValue) {
@@ -264,9 +295,14 @@ public class NotEqualsPredicateEvaluatorFactory {
       }
       return matches;
     }
+
+    @Override
+    public <R> R accept(SingleValueVisitor<R> visitor) {
+      return visitor.visitFloat(_nonMatchingValue);
+    }
   }
 
-  private static final class DoubleRawValueBasedNeqPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+  private static final class DoubleRawValueBasedNeqPredicateEvaluator extends 
NeqRawPredicateEvaluator {
     final double _nonMatchingValue;
 
     DoubleRawValueBasedNeqPredicateEvaluator(NotEqPredicate notEqPredicate, 
double nonMatchingValue) {
@@ -301,9 +337,14 @@ public class NotEqualsPredicateEvaluatorFactory {
       }
       return matches;
     }
+
+    @Override
+    public <R> R accept(SingleValueVisitor<R> visitor) {
+      return visitor.visitDouble(_nonMatchingValue);
+    }
   }
 
-  private static final class BigDecimalRawValueBasedNeqPredicateEvaluator 
extends BaseRawValueBasedPredicateEvaluator {
+  private static final class BigDecimalRawValueBasedNeqPredicateEvaluator 
extends NeqRawPredicateEvaluator {
     final BigDecimal _nonMatchingValue;
 
     BigDecimalRawValueBasedNeqPredicateEvaluator(NotEqPredicate 
notEqPredicate, BigDecimal nonMatchingValue) {
@@ -325,9 +366,14 @@ public class NotEqualsPredicateEvaluatorFactory {
     public boolean applySV(BigDecimal value) {
       return _nonMatchingValue.compareTo(value) != 0;
     }
+
+    @Override
+    public <R> R accept(SingleValueVisitor<R> visitor) {
+      return visitor.visitBigDecimal(_nonMatchingValue);
+    }
   }
 
-  private static final class StringRawValueBasedNeqPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+  private static final class StringRawValueBasedNeqPredicateEvaluator extends 
NeqRawPredicateEvaluator {
     final String _nonMatchingValue;
 
     StringRawValueBasedNeqPredicateEvaluator(NotEqPredicate notEqPredicate, 
String nonMatchingValue) {
@@ -349,9 +395,14 @@ public class NotEqualsPredicateEvaluatorFactory {
     public boolean applySV(String value) {
       return !_nonMatchingValue.equals(value);
     }
+
+    @Override
+    public <R> R accept(SingleValueVisitor<R> visitor) {
+      return visitor.visitString(_nonMatchingValue);
+    }
   }
 
-  private static final class BytesRawValueBasedNeqPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+  private static final class BytesRawValueBasedNeqPredicateEvaluator extends 
NeqRawPredicateEvaluator {
     final byte[] _nonMatchingValue;
 
     BytesRawValueBasedNeqPredicateEvaluator(NotEqPredicate notEqPredicate, 
byte[] nonMatchingValue) {
@@ -373,5 +424,10 @@ public class NotEqualsPredicateEvaluatorFactory {
     public boolean applySV(byte[] value) {
       return !Arrays.equals(_nonMatchingValue, value);
     }
+
+    @Override
+    public <R> R accept(SingleValueVisitor<R> visitor) {
+      return visitor.visitBytes(_nonMatchingValue);
+    }
   }
 }
diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/NotInPredicateEvaluatorFactory.java
 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/NotInPredicateEvaluatorFactory.java
index a0e2bf6a8d..5fe7b51d35 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/NotInPredicateEvaluatorFactory.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/predicate/NotInPredicateEvaluatorFactory.java
@@ -34,10 +34,12 @@ import java.util.Set;
 import java.util.TreeSet;
 import javax.annotation.Nullable;
 import org.apache.pinot.common.request.context.predicate.NotInPredicate;
+import org.apache.pinot.common.request.context.predicate.Predicate;
 import org.apache.pinot.common.utils.HashUtil;
 import org.apache.pinot.core.query.request.context.QueryContext;
 import org.apache.pinot.segment.spi.index.reader.Dictionary;
 import org.apache.pinot.spi.data.FieldSpec.DataType;
+import org.apache.pinot.spi.data.MultiValueVisitor;
 import org.apache.pinot.spi.utils.ByteArray;
 
 
@@ -69,7 +71,7 @@ public class NotInPredicateEvaluatorFactory {
    * @param dataType Data type for the column
    * @return Raw value based NOT_IN predicate evaluator
    */
-  public static BaseRawValueBasedPredicateEvaluator 
newRawValueBasedEvaluator(NotInPredicate notInPredicate,
+  public static NotInRawPredicateEvaluator 
newRawValueBasedEvaluator(NotInPredicate notInPredicate,
       DataType dataType) {
     switch (dataType) {
       case INT: {
@@ -225,7 +227,18 @@ public class NotInPredicateEvaluatorFactory {
     }
   }
 
-  private static final class IntRawValueBasedNotInPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+  public static abstract class NotInRawPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+    public NotInRawPredicateEvaluator(Predicate predicate) {
+      super(predicate);
+    }
+
+    /**
+     * Visits the not matching value of this predicate.
+     */
+    public abstract <R> R accept(MultiValueVisitor<R> visitor);
+  }
+
+  private static final class IntRawValueBasedNotInPredicateEvaluator extends 
NotInRawPredicateEvaluator {
     final IntSet _nonMatchingValues;
 
     IntRawValueBasedNotInPredicateEvaluator(NotInPredicate notInPredicate, 
IntSet nonMatchingValues) {
@@ -260,9 +273,14 @@ public class NotInPredicateEvaluatorFactory {
       }
       return matches;
     }
+
+    @Override
+    public <R> R accept(MultiValueVisitor<R> visitor) {
+      return visitor.visitInt(_nonMatchingValues.toIntArray());
+    }
   }
 
-  private static final class LongRawValueBasedNotInPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+  private static final class LongRawValueBasedNotInPredicateEvaluator extends 
NotInRawPredicateEvaluator {
     final LongSet _nonMatchingValues;
 
     LongRawValueBasedNotInPredicateEvaluator(NotInPredicate notInPredicate, 
LongSet nonMatchingValues) {
@@ -297,9 +315,14 @@ public class NotInPredicateEvaluatorFactory {
       }
       return matches;
     }
+
+    @Override
+    public <R> R accept(MultiValueVisitor<R> visitor) {
+      return visitor.visitLong(_nonMatchingValues.toLongArray());
+    }
   }
 
-  private static final class FloatRawValueBasedNotInPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+  private static final class FloatRawValueBasedNotInPredicateEvaluator extends 
NotInRawPredicateEvaluator {
     final FloatSet _nonMatchingValues;
 
     FloatRawValueBasedNotInPredicateEvaluator(NotInPredicate notInPredicate, 
FloatSet nonMatchingValues) {
@@ -334,9 +357,14 @@ public class NotInPredicateEvaluatorFactory {
       }
       return matches;
     }
+
+    @Override
+    public <R> R accept(MultiValueVisitor<R> visitor) {
+      return visitor.visitFloat(_nonMatchingValues.toFloatArray());
+    }
   }
 
-  private static final class DoubleRawValueBasedNotInPredicateEvaluator 
extends BaseRawValueBasedPredicateEvaluator {
+  private static final class DoubleRawValueBasedNotInPredicateEvaluator 
extends NotInRawPredicateEvaluator {
     final DoubleSet _nonMatchingValues;
 
     DoubleRawValueBasedNotInPredicateEvaluator(NotInPredicate notInPredicate, 
DoubleSet nonMatchingValues) {
@@ -371,10 +399,14 @@ public class NotInPredicateEvaluatorFactory {
       }
       return matches;
     }
+
+    @Override
+    public <R> R accept(MultiValueVisitor<R> visitor) {
+      return visitor.visitDouble(_nonMatchingValues.toDoubleArray());
+    }
   }
 
-  private static final class BigDecimalRawValueBasedNotInPredicateEvaluator
-      extends BaseRawValueBasedPredicateEvaluator {
+  private static final class BigDecimalRawValueBasedNotInPredicateEvaluator 
extends NotInRawPredicateEvaluator {
     // See: BigDecimalRawValueBasedInPredicateEvaluator.
     final TreeSet<BigDecimal> _nonMatchingValues;
 
@@ -398,9 +430,14 @@ public class NotInPredicateEvaluatorFactory {
     public boolean applySV(BigDecimal value) {
       return !_nonMatchingValues.contains(value);
     }
+
+    @Override
+    public <R> R accept(MultiValueVisitor<R> visitor) {
+      return visitor.visitBigDecimal(_nonMatchingValues.toArray(new 
BigDecimal[0]));
+    }
   }
 
-  private static final class StringRawValueBasedNotInPredicateEvaluator 
extends BaseRawValueBasedPredicateEvaluator {
+  private static final class StringRawValueBasedNotInPredicateEvaluator 
extends NotInRawPredicateEvaluator {
     final Set<String> _nonMatchingValues;
 
     StringRawValueBasedNotInPredicateEvaluator(NotInPredicate notInPredicate, 
Set<String> nonMatchingValues) {
@@ -422,9 +459,14 @@ public class NotInPredicateEvaluatorFactory {
     public boolean applySV(String value) {
       return !_nonMatchingValues.contains(value);
     }
+
+    @Override
+    public <R> R accept(MultiValueVisitor<R> visitor) {
+      return visitor.visitString(_nonMatchingValues.toArray(new String[0]));
+    }
   }
 
-  private static final class BytesRawValueBasedNotInPredicateEvaluator extends 
BaseRawValueBasedPredicateEvaluator {
+  private static final class BytesRawValueBasedNotInPredicateEvaluator extends 
NotInRawPredicateEvaluator {
     final Set<ByteArray> _nonMatchingValues;
 
     BytesRawValueBasedNotInPredicateEvaluator(NotInPredicate notInPredicate, 
Set<ByteArray> nonMatchingValues) {
@@ -446,5 +488,13 @@ public class NotInPredicateEvaluatorFactory {
     public boolean applySV(byte[] value) {
       return !_nonMatchingValues.contains(new ByteArray(value));
     }
+
+    @Override
+    public <R> R accept(MultiValueVisitor<R> visitor) {
+      byte[][] bytes = _nonMatchingValues.stream()
+          .map(ByteArray::getBytes)
+          .toArray(byte[][]::new);
+      return visitor.visitBytes(bytes);
+    }
   }
 }
diff --git 
a/pinot-core/src/test/java/org/apache/pinot/core/operator/filter/predicate/InPredicateEvaluatorFactoryTest.java
 
b/pinot-core/src/test/java/org/apache/pinot/core/operator/filter/predicate/InPredicateEvaluatorFactoryTest.java
new file mode 100644
index 0000000000..8e83e2b217
--- /dev/null
+++ 
b/pinot-core/src/test/java/org/apache/pinot/core/operator/filter/predicate/InPredicateEvaluatorFactoryTest.java
@@ -0,0 +1,115 @@
+/**
+ * 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.filter.predicate;
+
+import com.google.common.collect.Lists;
+import java.math.BigDecimal;
+import org.apache.pinot.common.request.context.ExpressionContext;
+import org.apache.pinot.common.request.context.predicate.InPredicate;
+import org.apache.pinot.spi.data.FieldSpec;
+import org.apache.pinot.spi.data.MultiValueVisitor;
+import org.mockito.Mockito;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+public class InPredicateEvaluatorFactoryTest {
+
+  MultiValueVisitor<Integer> createValueLengthVisitor() {
+    return new MultiValueVisitor<Integer>() {
+      @Override
+      public Integer visitInt(int[] value) {
+        return value.length;
+      }
+
+      @Override
+      public Integer visitLong(long[] value) {
+        return value.length;
+      }
+
+      @Override
+      public Integer visitFloat(float[] value) {
+        return value.length;
+      }
+
+      @Override
+      public Integer visitDouble(double[] value) {
+        return value.length;
+      }
+
+      @Override
+      public Integer visitBigDecimal(BigDecimal[] value) {
+        return value.length;
+      }
+
+      @Override
+      public Integer visitBoolean(boolean[] value) {
+        return value.length;
+      }
+
+      @Override
+      public Integer visitTimestamp(long[] value) {
+        return value.length;
+      }
+
+      @Override
+      public Integer visitString(String[] value) {
+        return value.length;
+      }
+
+      @Override
+      public Integer visitJson(String[] value) {
+        return value.length;
+      }
+
+      @Override
+      public Integer visitBytes(byte[][] value) {
+        return value.length;
+      }
+    };
+  }
+
+  @Test
+  void canBeVisited() {
+    // Given a visitor
+    MultiValueVisitor<Integer> valueLengthVisitor = 
Mockito.spy(createValueLengthVisitor());
+
+    // When int predicate is used
+    InPredicate predicate = new 
InPredicate(ExpressionContext.forIdentifier("ident"), Lists.newArrayList("1", 
"2"));
+
+    InPredicateEvaluatorFactory.InRawPredicateEvaluator intEvaluator =
+        InPredicateEvaluatorFactory.newRawValueBasedEvaluator(predicate, 
FieldSpec.DataType.INT);
+
+    // Only the int[] method is called
+    int length = intEvaluator.accept(valueLengthVisitor);
+    Assert.assertEquals(length, 2);
+    Mockito.verify(valueLengthVisitor).visitInt(new int[] {2, 1});
+    Mockito.verifyNoMoreInteractions(valueLengthVisitor);
+
+    // And given a string predicate
+    InPredicateEvaluatorFactory.InRawPredicateEvaluator strEvaluator =
+        InPredicateEvaluatorFactory.newRawValueBasedEvaluator(predicate, 
FieldSpec.DataType.STRING);
+
+    // Only the string[] method is called
+    length = strEvaluator.accept(valueLengthVisitor);
+    Assert.assertEquals(length, 2);
+    Mockito.verify(valueLengthVisitor).visitString(new String[] {"2", "1"});
+    Mockito.verifyNoMoreInteractions(valueLengthVisitor);
+  }
+}
diff --git 
a/pinot-spi/src/main/java/org/apache/pinot/spi/data/MultiValueVisitor.java 
b/pinot-spi/src/main/java/org/apache/pinot/spi/data/MultiValueVisitor.java
new file mode 100644
index 0000000000..13fc4d3568
--- /dev/null
+++ b/pinot-spi/src/main/java/org/apache/pinot/spi/data/MultiValueVisitor.java
@@ -0,0 +1,99 @@
+/**
+ * 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.spi.data;
+
+import java.math.BigDecimal;
+
+
+public interface MultiValueVisitor<R> {
+
+  R visitInt(int[] value);
+
+  R visitLong(long[] value);
+
+  R visitFloat(float[] value);
+
+  R visitDouble(double[] value);
+
+  R visitBigDecimal(BigDecimal[] value);
+
+  R visitBoolean(boolean[] value);
+
+  R visitTimestamp(long[] value);
+
+  R visitString(String[] value);
+
+  R visitJson(String[] value);
+
+  R visitBytes(byte[][] value);
+
+  default SingleValueVisitor<R> asSingleValueVisitor() {
+    return new SingleValueVisitor<R>() {
+      @Override
+      public R visitInt(int value) {
+        return MultiValueVisitor.this.visitInt(new int[] {value});
+      }
+
+      @Override
+      public R visitLong(long value) {
+        return MultiValueVisitor.this.visitLong(new long[] {value});
+      }
+
+      @Override
+      public R visitFloat(float value) {
+        return MultiValueVisitor.this.visitFloat(new float[] {value});
+      }
+
+      @Override
+      public R visitDouble(double value) {
+        return MultiValueVisitor.this.visitDouble(new double[] {value});
+      }
+
+      @Override
+      public R visitBigDecimal(BigDecimal value) {
+        return MultiValueVisitor.this.visitBigDecimal(new BigDecimal[] 
{value});
+      }
+
+      @Override
+      public R visitBoolean(boolean value) {
+        return MultiValueVisitor.this.visitBoolean(new boolean[] {value});
+      }
+
+      @Override
+      public R visitTimestamp(long value) {
+        return MultiValueVisitor.this.visitLong(new long[] {value});
+      }
+
+      @Override
+      public R visitString(String value) {
+        return MultiValueVisitor.this.visitString(new String[] {value});
+      }
+
+      @Override
+      public R visitJson(String value) {
+        return MultiValueVisitor.this.visitString(new String[] {value});
+      }
+
+      @Override
+      public R visitBytes(byte[] value) {
+        return MultiValueVisitor.this.visitBytes(new byte[][] {value});
+      }
+    };
+  }
+}
diff --git 
a/pinot-spi/src/main/java/org/apache/pinot/spi/data/SingleValueVisitor.java 
b/pinot-spi/src/main/java/org/apache/pinot/spi/data/SingleValueVisitor.java
new file mode 100644
index 0000000000..6184bbf057
--- /dev/null
+++ b/pinot-spi/src/main/java/org/apache/pinot/spi/data/SingleValueVisitor.java
@@ -0,0 +1,45 @@
+/**
+ * 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.spi.data;
+
+import java.math.BigDecimal;
+
+
+public interface SingleValueVisitor<R> {
+
+  R visitInt(int value);
+
+  R visitLong(long value);
+
+  R visitFloat(float value);
+
+  R visitDouble(double value);
+
+  R visitBigDecimal(BigDecimal value);
+
+  R visitBoolean(boolean value);
+
+  R visitTimestamp(long value);
+
+  R visitString(String value);
+
+  R visitJson(String value);
+
+  R visitBytes(byte[] value);
+}


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


Reply via email to