You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pinot.apache.org by ja...@apache.org on 2023/11/07 16:48:00 UTC
(pinot) branch master updated: Support constant filter in QueryContext, and make server able to handle it (#11956)
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 45f186903e Support constant filter in QueryContext, and make server able to handle it (#11956)
45f186903e is described below
commit 45f186903e0d35304fb764ccb5f1423839d3276b
Author: Xiaotian (Jackie) Jiang <17...@users.noreply.github.com>
AuthorDate: Tue Nov 7 08:47:54 2023 -0800
Support constant filter in QueryContext, and make server able to handle it (#11956)
---
.../common/request/context/FilterContext.java | 73 +++++--
.../request/context/RequestContextUtils.java | 236 +++++++++++++--------
.../controller/recommender/io/InputManager.java | 8 +-
.../recommender/rules/impl/BloomFilterRule.java | 7 +-
.../recommender/rules/impl/FlagQueryRule.java | 6 +-
.../NoDictionaryOnHeapDictionaryJointRule.java | 5 +-
.../rules/impl/PinotTablePartitionRule.java | 7 +-
.../recommender/rules/impl/RangeIndexRule.java | 5 +-
.../utils/QueryInvertedSortedIndexRecommender.java | 7 +-
...istinctCountThetaSketchAggregationFunction.java | 2 +-
.../query/executor/ServerQueryExecutorV1Impl.java | 23 +-
.../context/utils/QueryContextConverterUtils.java | 8 +
.../BrokerRequestToQueryContextConverterTest.java | 89 ++++++--
.../realtime/impl/json/MutableJsonIndexImpl.java | 1 +
.../readers/json/ImmutableJsonIndexReader.java | 1 +
15 files changed, 330 insertions(+), 148 deletions(-)
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/context/FilterContext.java b/pinot-common/src/main/java/org/apache/pinot/common/request/context/FilterContext.java
index aa76809b68..3ce48fd06c 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/context/FilterContext.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/context/FilterContext.java
@@ -18,9 +18,11 @@
*/
package org.apache.pinot.common.request.context;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
+import javax.annotation.Nullable;
import org.apache.pinot.common.request.context.predicate.Predicate;
@@ -29,22 +31,50 @@ import org.apache.pinot.common.request.context.predicate.Predicate;
* clause are modeled as a filter.
*/
public class FilterContext {
+ public static final FilterContext CONSTANT_TRUE = new FilterContext(Type.CONSTANT, null, null, true);
+ public static final FilterContext CONSTANT_FALSE = new FilterContext(Type.CONSTANT, null, null, false);
+
public enum Type {
- AND, OR, NOT, PREDICATE
+ AND, OR, NOT, PREDICATE, CONSTANT
}
private final Type _type;
- // For AND and OR
+ // For AND, OR, NOT
private final List<FilterContext> _children;
// For Predicate
private final Predicate _predicate;
- public FilterContext(Type type, List<FilterContext> children, Predicate predicate) {
+ // For Constant
+ private final boolean _isTrue;
+
+ private FilterContext(Type type, @Nullable List<FilterContext> children, @Nullable Predicate predicate,
+ boolean isTrue) {
_type = type;
_children = children;
_predicate = predicate;
+ _isTrue = isTrue;
+ }
+
+ public static FilterContext forAnd(List<FilterContext> children) {
+ return new FilterContext(Type.AND, children, null, false);
+ }
+
+ public static FilterContext forOr(List<FilterContext> children) {
+ return new FilterContext(Type.OR, children, null, false);
+ }
+
+ public static FilterContext forNot(FilterContext child) {
+ return new FilterContext(Type.NOT, Collections.singletonList(child), null, false);
+ }
+
+ public static FilterContext forPredicate(Predicate predicate) {
+ return new FilterContext(Type.PREDICATE, null, predicate, false);
+ }
+
+ public static FilterContext forConstant(boolean isTrue) {
+ return isTrue ? CONSTANT_TRUE : CONSTANT_FALSE;
}
public Type getType() {
@@ -59,6 +89,18 @@ public class FilterContext {
return _predicate;
}
+ public boolean isConstant() {
+ return _type == Type.CONSTANT;
+ }
+
+ public boolean isConstantTrue() {
+ return _isTrue;
+ }
+
+ public boolean isConstantFalse() {
+ return _type == Type.CONSTANT && !_isTrue;
+ }
+
/**
* Adds the columns (IDENTIFIER expressions) in the filter to the given set.
*/
@@ -67,7 +109,7 @@ public class FilterContext {
for (FilterContext child : _children) {
child.getColumns(columns);
}
- } else {
+ } else if (_predicate != null) {
_predicate.getLhs().getColumns(columns);
}
}
@@ -81,37 +123,44 @@ public class FilterContext {
return false;
}
FilterContext that = (FilterContext) o;
- return _type == that._type && Objects.equals(_children, that._children) && Objects.equals(_predicate,
- that._predicate);
+ return _isTrue == that._isTrue && _type == that._type && Objects.equals(_children, that._children)
+ && Objects.equals(_predicate, that._predicate);
}
@Override
public int hashCode() {
- return Objects.hash(_type, _children, _predicate);
+ return Objects.hash(_type, _children, _predicate, _isTrue);
}
@Override
public String toString() {
switch (_type) {
- case AND:
+ case AND: {
+ assert _children != null;
StringBuilder stringBuilder = new StringBuilder().append('(').append(_children.get(0));
int numChildren = _children.size();
for (int i = 1; i < numChildren; i++) {
stringBuilder.append(" AND ").append(_children.get(i));
}
return stringBuilder.append(')').toString();
- case OR:
- stringBuilder = new StringBuilder().append('(').append(_children.get(0));
- numChildren = _children.size();
+ }
+ case OR: {
+ assert _children != null;
+ StringBuilder stringBuilder = new StringBuilder().append('(').append(_children.get(0));
+ int numChildren = _children.size();
for (int i = 1; i < numChildren; i++) {
stringBuilder.append(" OR ").append(_children.get(i));
}
return stringBuilder.append(')').toString();
+ }
case NOT:
- assert _children.size() == 1;
+ assert _children != null && _children.size() == 1;
return "(NOT " + _children.get(0) + ')';
case PREDICATE:
+ assert _predicate != null;
return _predicate.toString();
+ case CONSTANT:
+ return Boolean.toString(_isTrue);
default:
throw new IllegalStateException();
}
diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/context/RequestContextUtils.java b/pinot-common/src/main/java/org/apache/pinot/common/request/context/RequestContextUtils.java
index 96bfb226e1..933f022bfb 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/context/RequestContextUtils.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/context/RequestContextUtils.java
@@ -111,11 +111,9 @@ public class RequestContextUtils {
return getFilter(thriftFunction);
case IDENTIFIER:
// Convert "WHERE a" to "WHERE a = true"
- return new FilterContext(FilterContext.Type.PREDICATE, null,
- new EqPredicate(getExpression(thriftExpression), getStringValue(RequestUtils.getLiteralExpression(true))));
+ return FilterContext.forPredicate(new EqPredicate(getExpression(thriftExpression), "true"));
case LITERAL:
- // TODO: Handle literals.
- throw new IllegalStateException();
+ return FilterContext.forConstant(new LiteralContext(thriftExpression.getLiteral()).getBooleanValue());
default:
throw new IllegalStateException();
}
@@ -126,96 +124,127 @@ public class RequestContextUtils {
// convert "WHERE startsWith(col, 'str')" to "WHERE startsWith(col, 'str') = true"
if (!EnumUtils.isValidEnum(FilterKind.class, functionOperator)) {
- return new FilterContext(FilterContext.Type.PREDICATE, null,
- new EqPredicate(ExpressionContext.forFunction(getFunction(thriftFunction)),
- getStringValue(RequestUtils.getLiteralExpression(true))));
+ return FilterContext.forPredicate(
+ new EqPredicate(ExpressionContext.forFunction(getFunction(thriftFunction)), "true"));
}
FilterKind filterKind = FilterKind.valueOf(thriftFunction.getOperator().toUpperCase());
List<Expression> operands = thriftFunction.getOperands();
int numOperands = operands.size();
switch (filterKind) {
- case AND:
+ case AND: {
List<FilterContext> children = new ArrayList<>(numOperands);
for (Expression operand : operands) {
- children.add(getFilter(operand));
+ FilterContext filter = getFilter(operand);
+ if (!filter.isConstant()) {
+ children.add(filter);
+ } else {
+ if (filter.isConstantFalse()) {
+ return FilterContext.CONSTANT_FALSE;
+ }
+ }
+ }
+ int numChildren = children.size();
+ if (numChildren == 0) {
+ return FilterContext.CONSTANT_TRUE;
+ } else if (numChildren == 1) {
+ return children.get(0);
+ } else {
+ return FilterContext.forAnd(children);
}
- return new FilterContext(FilterContext.Type.AND, children, null);
- case OR:
- children = new ArrayList<>(numOperands);
+ }
+ case OR: {
+ List<FilterContext> children = new ArrayList<>(numOperands);
for (Expression operand : operands) {
- children.add(getFilter(operand));
+ FilterContext filter = getFilter(operand);
+ if (!filter.isConstant()) {
+ children.add(filter);
+ } else {
+ if (filter.isConstantTrue()) {
+ return FilterContext.CONSTANT_TRUE;
+ }
+ }
}
- return new FilterContext(FilterContext.Type.OR, children, null);
- case NOT:
+ int numChildren = children.size();
+ if (numChildren == 0) {
+ return FilterContext.CONSTANT_FALSE;
+ } else if (numChildren == 1) {
+ return children.get(0);
+ } else {
+ return FilterContext.forOr(children);
+ }
+ }
+ case NOT: {
assert numOperands == 1;
- return new FilterContext(FilterContext.Type.NOT,
- new ArrayList<>(Collections.singletonList(getFilter(operands.get(0)))), null);
+ FilterContext filter = getFilter(operands.get(0));
+ if (!filter.isConstant()) {
+ return FilterContext.forNot(filter);
+ } else {
+ return filter.isConstantTrue() ? FilterContext.CONSTANT_FALSE : FilterContext.CONSTANT_TRUE;
+ }
+ }
case EQUALS:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
+ return FilterContext.forPredicate(
new EqPredicate(getExpression(operands.get(0)), getStringValue(operands.get(1))));
case NOT_EQUALS:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
+ return FilterContext.forPredicate(
new NotEqPredicate(getExpression(operands.get(0)), getStringValue(operands.get(1))));
- case IN:
+ case IN: {
List<String> values = new ArrayList<>(numOperands - 1);
for (int i = 1; i < numOperands; i++) {
values.add(getStringValue(operands.get(i)));
}
- return new FilterContext(FilterContext.Type.PREDICATE, null,
- new InPredicate(getExpression(operands.get(0)), values));
- case NOT_IN:
- values = new ArrayList<>(numOperands - 1);
+ return FilterContext.forPredicate(new InPredicate(getExpression(operands.get(0)), values));
+ }
+ case NOT_IN: {
+ List<String> values = new ArrayList<>(numOperands - 1);
for (int i = 1; i < numOperands; i++) {
values.add(getStringValue(operands.get(i)));
}
- return new FilterContext(FilterContext.Type.PREDICATE, null,
- new NotInPredicate(getExpression(operands.get(0)), values));
+ return FilterContext.forPredicate(new NotInPredicate(getExpression(operands.get(0)), values));
+ }
case GREATER_THAN:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
+ return FilterContext.forPredicate(
new RangePredicate(getExpression(operands.get(0)), false, getStringValue(operands.get(1)), false,
RangePredicate.UNBOUNDED));
case GREATER_THAN_OR_EQUAL:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
+ return FilterContext.forPredicate(
new RangePredicate(getExpression(operands.get(0)), true, getStringValue(operands.get(1)), false,
RangePredicate.UNBOUNDED));
case LESS_THAN:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
+ return FilterContext.forPredicate(
new RangePredicate(getExpression(operands.get(0)), false, RangePredicate.UNBOUNDED, false,
getStringValue(operands.get(1))));
case LESS_THAN_OR_EQUAL:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
+ return FilterContext.forPredicate(
new RangePredicate(getExpression(operands.get(0)), false, RangePredicate.UNBOUNDED, true,
getStringValue(operands.get(1))));
case BETWEEN:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
+ return FilterContext.forPredicate(
new RangePredicate(getExpression(operands.get(0)), true, getStringValue(operands.get(1)), true,
getStringValue(operands.get(2))));
case RANGE:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
+ return FilterContext.forPredicate(
new RangePredicate(getExpression(operands.get(0)), getStringValue(operands.get(1))));
case REGEXP_LIKE:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
+ return FilterContext.forPredicate(
new RegexpLikePredicate(getExpression(operands.get(0)), getStringValue(operands.get(1))));
case LIKE:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
- new RegexpLikePredicate(getExpression(operands.get(0)),
- RegexpPatternConverterUtils.likeToRegexpLike(getStringValue(operands.get(1)))));
+ return FilterContext.forPredicate(new RegexpLikePredicate(getExpression(operands.get(0)),
+ RegexpPatternConverterUtils.likeToRegexpLike(getStringValue(operands.get(1)))));
case TEXT_CONTAINS:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
+ return FilterContext.forPredicate(
new TextContainsPredicate(getExpression(operands.get(0)), getStringValue(operands.get(1))));
case TEXT_MATCH:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
+ return FilterContext.forPredicate(
new TextMatchPredicate(getExpression(operands.get(0)), getStringValue(operands.get(1))));
case JSON_MATCH:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
+ return FilterContext.forPredicate(
new JsonMatchPredicate(getExpression(operands.get(0)), getStringValue(operands.get(1))));
case IS_NULL:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
- new IsNullPredicate(getExpression(operands.get(0))));
+ return FilterContext.forPredicate(new IsNullPredicate(getExpression(operands.get(0))));
case IS_NOT_NULL:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
- new IsNotNullPredicate(getExpression(operands.get(0))));
+ return FilterContext.forPredicate(new IsNotNullPredicate(getExpression(operands.get(0))));
default:
throw new IllegalStateException();
}
@@ -245,11 +274,10 @@ public class RequestContextUtils {
FunctionContext filterFunction = filterExpression.getFunction();
return getFilter(filterFunction);
case IDENTIFIER:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
+ return FilterContext.forPredicate(
new EqPredicate(filterExpression, getStringValue(RequestUtils.getLiteralExpression(true))));
case LITERAL:
- // TODO: Handle literals
- throw new IllegalStateException();
+ return FilterContext.forConstant(filterExpression.getLiteral().getBooleanValue());
default:
throw new IllegalStateException();
}
@@ -260,91 +288,117 @@ public class RequestContextUtils {
// convert "WHERE startsWith(col, 'str')" to "WHERE startsWith(col, 'str') = true"
if (!EnumUtils.isValidEnum(FilterKind.class, functionOperator)) {
- return new FilterContext(FilterContext.Type.PREDICATE, null,
- new EqPredicate(ExpressionContext.forFunction(filterFunction),
- getStringValue(RequestUtils.getLiteralExpression(true))));
+ return FilterContext.forPredicate(new EqPredicate(ExpressionContext.forFunction(filterFunction), "true"));
}
FilterKind filterKind = FilterKind.valueOf(filterFunction.getFunctionName().toUpperCase());
List<ExpressionContext> operands = filterFunction.getArguments();
int numOperands = operands.size();
switch (filterKind) {
- case AND:
+ case AND: {
List<FilterContext> children = new ArrayList<>(numOperands);
for (ExpressionContext operand : operands) {
- children.add(getFilter(operand));
+ FilterContext filter = getFilter(operand);
+ if (!filter.isConstant()) {
+ children.add(filter);
+ } else {
+ if (filter.isConstantFalse()) {
+ return FilterContext.CONSTANT_FALSE;
+ }
+ }
}
- return new FilterContext(FilterContext.Type.AND, children, null);
- case OR:
- children = new ArrayList<>(numOperands);
+ int numChildren = children.size();
+ if (numChildren == 0) {
+ return FilterContext.CONSTANT_TRUE;
+ } else if (numChildren == 1) {
+ return children.get(0);
+ } else {
+ return FilterContext.forAnd(children);
+ }
+ }
+ case OR: {
+ List<FilterContext> children = new ArrayList<>(numOperands);
for (ExpressionContext operand : operands) {
- children.add(getFilter(operand));
+ FilterContext filter = getFilter(operand);
+ if (!filter.isConstant()) {
+ children.add(filter);
+ } else {
+ if (filter.isConstantTrue()) {
+ return FilterContext.CONSTANT_TRUE;
+ }
+ }
}
- return new FilterContext(FilterContext.Type.OR, children, null);
- case NOT:
+ int numChildren = children.size();
+ if (numChildren == 0) {
+ return FilterContext.CONSTANT_FALSE;
+ } else if (numChildren == 1) {
+ return children.get(0);
+ } else {
+ return FilterContext.forOr(children);
+ }
+ }
+ case NOT: {
assert numOperands == 1;
- return new FilterContext(FilterContext.Type.NOT,
- new ArrayList<>(Collections.singletonList(getFilter(operands.get(0)))), null);
+ FilterContext filter = getFilter(operands.get(0));
+ if (!filter.isConstant()) {
+ return FilterContext.forNot(filter);
+ } else {
+ return filter.isConstantTrue() ? FilterContext.CONSTANT_FALSE : FilterContext.CONSTANT_TRUE;
+ }
+ }
case EQUALS:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
- new EqPredicate(operands.get(0), getStringValue(operands.get(1))));
+ return FilterContext.forPredicate(new EqPredicate(operands.get(0), getStringValue(operands.get(1))));
case NOT_EQUALS:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
- new NotEqPredicate(operands.get(0), getStringValue(operands.get(1))));
- case IN:
+ return FilterContext.forPredicate(new NotEqPredicate(operands.get(0), getStringValue(operands.get(1))));
+ case IN: {
List<String> values = new ArrayList<>(numOperands - 1);
for (int i = 1; i < numOperands; i++) {
values.add(getStringValue(operands.get(i)));
}
- return new FilterContext(FilterContext.Type.PREDICATE, null, new InPredicate(operands.get(0), values));
- case NOT_IN:
- values = new ArrayList<>(numOperands - 1);
+ return FilterContext.forPredicate(new InPredicate(operands.get(0), values));
+ }
+ case NOT_IN: {
+ List<String> values = new ArrayList<>(numOperands - 1);
for (int i = 1; i < numOperands; i++) {
values.add(getStringValue(operands.get(i)));
}
- return new FilterContext(FilterContext.Type.PREDICATE, null, new NotInPredicate(operands.get(0), values));
+ return FilterContext.forPredicate(new NotInPredicate(operands.get(0), values));
+ }
case GREATER_THAN:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
+ return FilterContext.forPredicate(
new RangePredicate(operands.get(0), false, getStringValue(operands.get(1)), false,
RangePredicate.UNBOUNDED));
case GREATER_THAN_OR_EQUAL:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
+ return FilterContext.forPredicate(
new RangePredicate(operands.get(0), true, getStringValue(operands.get(1)), false,
RangePredicate.UNBOUNDED));
case LESS_THAN:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
- new RangePredicate(operands.get(0), false, RangePredicate.UNBOUNDED, false,
- getStringValue(operands.get(1))));
+ return FilterContext.forPredicate(new RangePredicate(operands.get(0), false, RangePredicate.UNBOUNDED, false,
+ getStringValue(operands.get(1))));
case LESS_THAN_OR_EQUAL:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
- new RangePredicate(operands.get(0), false, RangePredicate.UNBOUNDED, true,
- getStringValue(operands.get(1))));
+ return FilterContext.forPredicate(new RangePredicate(operands.get(0), false, RangePredicate.UNBOUNDED, true,
+ getStringValue(operands.get(1))));
case BETWEEN:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
+ return FilterContext.forPredicate(
new RangePredicate(operands.get(0), true, getStringValue(operands.get(1)), true,
getStringValue(operands.get(2))));
case RANGE:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
- new RangePredicate(operands.get(0), getStringValue(operands.get(1))));
+ return FilterContext.forPredicate(new RangePredicate(operands.get(0), getStringValue(operands.get(1))));
case REGEXP_LIKE:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
- new RegexpLikePredicate(operands.get(0), getStringValue(operands.get(1))));
+ return FilterContext.forPredicate(new RegexpLikePredicate(operands.get(0), getStringValue(operands.get(1))));
case LIKE:
- return new FilterContext(FilterContext.Type.PREDICATE, null, new RegexpLikePredicate(operands.get(0),
+ return FilterContext.forPredicate(new RegexpLikePredicate(operands.get(0),
RegexpPatternConverterUtils.likeToRegexpLike(getStringValue(operands.get(1)))));
case TEXT_CONTAINS:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
- new TextContainsPredicate(operands.get(0), getStringValue(operands.get(1))));
+ return FilterContext.forPredicate(new TextContainsPredicate(operands.get(0), getStringValue(operands.get(1))));
case TEXT_MATCH:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
- new TextMatchPredicate(operands.get(0), getStringValue(operands.get(1))));
+ return FilterContext.forPredicate(new TextMatchPredicate(operands.get(0), getStringValue(operands.get(1))));
case JSON_MATCH:
- return new FilterContext(FilterContext.Type.PREDICATE, null,
- new JsonMatchPredicate(operands.get(0), getStringValue(operands.get(1))));
+ return FilterContext.forPredicate(new JsonMatchPredicate(operands.get(0), getStringValue(operands.get(1))));
case IS_NULL:
- return new FilterContext(FilterContext.Type.PREDICATE, null, new IsNullPredicate(operands.get(0)));
+ return FilterContext.forPredicate(new IsNullPredicate(operands.get(0)));
case IS_NOT_NULL:
- return new FilterContext(FilterContext.Type.PREDICATE, null, new IsNotNullPredicate(operands.get(0)));
+ return FilterContext.forPredicate(new IsNotNullPredicate(operands.get(0)));
default:
throw new IllegalStateException();
}
@@ -354,7 +408,7 @@ public class RequestContextUtils {
// literal context doesn't support float, and we cannot differentiate explicit string literal and literal
// without explicit type, so we always convert the literal into string.
private static String getStringValue(ExpressionContext expressionContext) {
- if(expressionContext.getType() != ExpressionContext.Type.LITERAL){
+ if (expressionContext.getType() != ExpressionContext.Type.LITERAL) {
throw new BadQueryRequestException(
"Pinot does not support column or function on the right-hand side of the predicate");
}
diff --git a/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/io/InputManager.java b/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/io/InputManager.java
index 4834866c51..412c1d2421 100644
--- a/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/io/InputManager.java
+++ b/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/io/InputManager.java
@@ -35,6 +35,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.lang3.tuple.Triple;
import org.apache.pinot.common.request.BrokerRequest;
import org.apache.pinot.common.request.PinotQuery;
+import org.apache.pinot.common.request.context.FilterContext;
import org.apache.pinot.controller.recommender.exceptions.InvalidInputException;
import org.apache.pinot.controller.recommender.io.metadata.FieldMetadata;
import org.apache.pinot.controller.recommender.io.metadata.SchemaWithMetaData;
@@ -177,10 +178,11 @@ public class InputManager {
// Flag the queries having in filter columns not appear in schema
// to exclude user input like select i from tableName where a = xyz and t > 500
- Set<String> filterColumns = new HashSet<>();
- if (queryContext.getFilter() != null) {
+ FilterContext filter = queryContext.getFilter();
+ if (filter != null && !filter.isConstant()) {
+ Set<String> filterColumns = new HashSet<>();
// get in filter column names, excluding literals, etc
- queryContext.getFilter().getColumns(filterColumns);
+ filter.getColumns(filterColumns);
// remove those appear in schema
filterColumns.removeAll(_colNameToIntMap.keySet());
// flag if there are columns left
diff --git a/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/impl/BloomFilterRule.java b/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/impl/BloomFilterRule.java
index 5a9de70e5d..2ac5daa22c 100644
--- a/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/impl/BloomFilterRule.java
+++ b/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/impl/BloomFilterRule.java
@@ -87,12 +87,13 @@ public class BloomFilterRule extends AbstractRule {
}
public FixedLenBitset parseQuery(QueryContext queryContext) {
- if (queryContext.getFilter() == null) {
+ FilterContext filter = queryContext.getFilter();
+ if (filter == null || filter.isConstant()) {
return FixedLenBitset.IMMUTABLE_EMPTY_SET;
}
- LOGGER.trace("Parsing Where Clause: {}", queryContext.getFilter().toString());
- return parsePredicateList(queryContext.getFilter());
+ LOGGER.trace("Parsing Where Clause: {}", filter);
+ return parsePredicateList(filter);
}
/**
diff --git a/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/impl/FlagQueryRule.java b/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/impl/FlagQueryRule.java
index 8995f3857e..60533be596 100644
--- a/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/impl/FlagQueryRule.java
+++ b/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/impl/FlagQueryRule.java
@@ -21,6 +21,7 @@ package org.apache.pinot.controller.recommender.rules.impl;
import java.util.HashSet;
import java.util.Set;
+import org.apache.pinot.common.request.context.FilterContext;
import org.apache.pinot.controller.recommender.io.ConfigManager;
import org.apache.pinot.controller.recommender.io.InputManager;
import org.apache.pinot.controller.recommender.rules.AbstractRule;
@@ -59,12 +60,13 @@ public class FlagQueryRule extends AbstractRule {
_output.getFlaggedQueries().add(query, WARNING_TOO_LONG_LIMIT);
}
- if (queryContext.getFilter() == null) {
+ FilterContext filter = queryContext.getFilter();
+ if (filter == null || filter.isConstant()) {
//Flag the queries that are not using any filters.
_output.getFlaggedQueries().add(query, WARNING_NO_FILTERING);
} else { //Flag the queries that are not using any time filters.
Set<String> usedCols = new HashSet<>();
- queryContext.getFilter().getColumns(usedCols);
+ filter.getColumns(usedCols);
Set<String> timeCols = _input.getTimeColumns();
if (!timeCols.isEmpty()) {
usedCols.retainAll(timeCols);
diff --git a/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/impl/NoDictionaryOnHeapDictionaryJointRule.java b/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/impl/NoDictionaryOnHeapDictionaryJointRule.java
index 6b07f56254..03d2acf9bf 100644
--- a/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/impl/NoDictionaryOnHeapDictionaryJointRule.java
+++ b/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/impl/NoDictionaryOnHeapDictionaryJointRule.java
@@ -197,8 +197,9 @@ public class NoDictionaryOnHeapDictionaryJointRule extends AbstractRule {
});
}
- if (queryContext.getFilter() != null) {
- fixedLenBitsetFilterGroupBy.union(parsePredicateList(queryContext.getFilter()));
+ FilterContext filter = queryContext.getFilter();
+ if (filter != null && !filter.isConstant()) {
+ fixedLenBitsetFilterGroupBy.union(parsePredicateList(filter));
}
for (Integer colId : fixedLenBitsetFilterGroupBy.getOffsets()) {
diff --git a/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/impl/PinotTablePartitionRule.java b/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/impl/PinotTablePartitionRule.java
index ca879d735c..609c91cf86 100644
--- a/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/impl/PinotTablePartitionRule.java
+++ b/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/impl/PinotTablePartitionRule.java
@@ -184,12 +184,13 @@ public class PinotTablePartitionRule extends AbstractRule {
* See PartitionSegmentPruner
*/
public FixedLenBitset parseQuery(QueryContext queryContext) {
- if (queryContext.getFilter() == null) {
+ FilterContext filter = queryContext.getFilter();
+ if (filter == null || filter.isConstant()) {
return FixedLenBitset.IMMUTABLE_EMPTY_SET;
}
- LOGGER.trace("Parsing Where Clause: {}", queryContext.getFilter().toString());
- return parsePredicateList(queryContext.getFilter());
+ LOGGER.trace("Parsing Where Clause: {}", filter);
+ return parsePredicateList(filter);
}
@Nullable
diff --git a/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/impl/RangeIndexRule.java b/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/impl/RangeIndexRule.java
index 17424923cb..360dae4e68 100644
--- a/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/impl/RangeIndexRule.java
+++ b/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/impl/RangeIndexRule.java
@@ -79,11 +79,12 @@ public class RangeIndexRule extends AbstractRule {
}
public FixedLenBitset parseQuery(QueryContext queryContext) {
- if (queryContext.getFilter() == null) {
+ FilterContext filter = queryContext.getFilter();
+ if (filter == null || filter.isConstant()) {
return FixedLenBitset.IMMUTABLE_EMPTY_SET;
}
- return parsePredicateList(queryContext.getFilter());
+ return parsePredicateList(filter);
}
/**
diff --git a/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/utils/QueryInvertedSortedIndexRecommender.java b/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/utils/QueryInvertedSortedIndexRecommender.java
index 749b137144..f0eb891a13 100644
--- a/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/utils/QueryInvertedSortedIndexRecommender.java
+++ b/pinot-controller/src/main/java/org/apache/pinot/controller/recommender/rules/utils/QueryInvertedSortedIndexRecommender.java
@@ -87,12 +87,13 @@ public class QueryInvertedSortedIndexRecommender {
* meaning that at most one candidate (PredicateParseResult) in the list can contribute to the global recommendation.
*/
public List<List<PredicateParseResult>> parseQuery(QueryContext queryContext, double queryWeight) {
- if (queryContext.getFilter() == null) {
+ FilterContext filter = queryContext.getFilter();
+ if (filter == null || filter.isConstant()) {
return EMPTY_PARSE_RESULT;
}
- LOGGER.trace("Parsing Where Clause: {}", queryContext.getFilter().toString());
- return parseTopLevel(queryContext.getFilter(), queryWeight);
+ LOGGER.trace("Parsing Where Clause: {}", filter);
+ return parseTopLevel(filter, queryWeight);
}
/**
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/DistinctCountThetaSketchAggregationFunction.java b/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/DistinctCountThetaSketchAggregationFunction.java
index c6a57b373f..f3a9adfda6 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/DistinctCountThetaSketchAggregationFunction.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/DistinctCountThetaSketchAggregationFunction.java
@@ -132,6 +132,7 @@ public class DistinctCountThetaSketchAggregationFunction
+ "(filter expression)");
FilterContext filter = RequestContextUtils.getFilter(
CalciteSqlParser.compileToExpression(filterExpression.getLiteral().getStringValue()));
+ Preconditions.checkArgument(!filter.isConstant(), "Filter must not be constant: %s", filter);
// NOTE: Collect expressions before constructing the FilterInfo so that expressionIndexMap always include the
// expressions in the filter.
collectExpressions(filter, _inputExpressions, expressionIndexMap);
@@ -146,7 +147,6 @@ public class DistinctCountThetaSketchAggregationFunction
Expression expr = CalciteSqlParser.compileToExpression(postAggregationExpression.getLiteral().getStringValue());
_postAggregationExpression = RequestContextUtils.getExpression(expr);
-
// Validate the post-aggregation expression
_includeDefaultSketch = validatePostAggregationExpression(_postAggregationExpression, _filterEvaluators.size());
}
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/query/executor/ServerQueryExecutorV1Impl.java b/pinot-core/src/main/java/org/apache/pinot/core/query/executor/ServerQueryExecutorV1Impl.java
index 4c3248e527..17ce5ae159 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/query/executor/ServerQueryExecutorV1Impl.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/query/executor/ServerQueryExecutorV1Impl.java
@@ -20,6 +20,7 @@ package org.apache.pinot.core.query.executor;
import com.google.common.base.Preconditions;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -349,12 +350,18 @@ public class ServerQueryExecutorV1Impl implements QueryExecutor {
numTotalDocs += indexSegment.getSegmentMetadata().getTotalDocs();
}
- TimerContext.Timer segmentPruneTimer = timerContext.startNewPhaseTimer(ServerQueryPhase.SEGMENT_PRUNING);
+ List<IndexSegment> selectedSegments;
+ SegmentPrunerStatistics prunerStats = null;
+ if ((queryContext.getFilter() != null && queryContext.getFilter().isConstantFalse()) || (
+ queryContext.getHavingFilter() != null && queryContext.getHavingFilter().isConstantFalse())) {
+ selectedSegments = Collections.emptyList();
+ } else {
+ TimerContext.Timer segmentPruneTimer = timerContext.startNewPhaseTimer(ServerQueryPhase.SEGMENT_PRUNING);
+ prunerStats = new SegmentPrunerStatistics();
+ selectedSegments = _segmentPrunerService.prune(indexSegments, queryContext, prunerStats, executorService);
+ segmentPruneTimer.stopAndRecord();
+ }
int numTotalSegments = indexSegments.size();
- SegmentPrunerStatistics prunerStats = new SegmentPrunerStatistics();
- List<IndexSegment> selectedSegments =
- _segmentPrunerService.prune(indexSegments, queryContext, prunerStats, executorService);
- segmentPruneTimer.stopAndRecord();
int numSelectedSegments = selectedSegments.size();
LOGGER.debug("Matched {} segments after pruning", numSelectedSegments);
InstanceResponseBlock instanceResponse;
@@ -383,7 +390,9 @@ public class ServerQueryExecutorV1Impl implements QueryExecutor {
// Set the number of pruned segments. This count does not include the segments which returned empty filters
int prunedSegments = numTotalSegments - numSelectedSegments;
instanceResponse.addMetadata(MetadataKey.NUM_SEGMENTS_PRUNED_BY_SERVER.getName(), String.valueOf(prunedSegments));
- addPrunerStats(instanceResponse, prunerStats);
+ if (prunerStats != null) {
+ addPrunerStats(instanceResponse, prunerStats);
+ }
return instanceResponse;
}
@@ -512,7 +521,7 @@ public class ServerQueryExecutorV1Impl implements QueryExecutor {
ExecutorService executorService)
throws Exception {
FilterContext filter = queryContext.getFilter();
- if (filter != null) {
+ if (filter != null && !filter.isConstant()) {
handleSubquery(filter, indexSegments, timerContext, executorService, queryContext.getEndTimeMs());
}
}
diff --git a/pinot-core/src/main/java/org/apache/pinot/core/query/request/context/utils/QueryContextConverterUtils.java b/pinot-core/src/main/java/org/apache/pinot/core/query/request/context/utils/QueryContextConverterUtils.java
index 4de58610de..47a89be814 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/query/request/context/utils/QueryContextConverterUtils.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/query/request/context/utils/QueryContextConverterUtils.java
@@ -96,6 +96,10 @@ public class QueryContextConverterUtils {
Expression filterExpression = pinotQuery.getFilterExpression();
if (filterExpression != null) {
filter = RequestContextUtils.getFilter(filterExpression);
+ // Remove the filter if it is always true
+ if (filter.isConstantTrue()) {
+ filter = null;
+ }
}
// GROUP BY
@@ -135,6 +139,10 @@ public class QueryContextConverterUtils {
Expression havingExpression = pinotQuery.getHavingExpression();
if (havingExpression != null) {
havingFilter = RequestContextUtils.getFilter(havingExpression);
+ // Remove the filter if it is always true
+ if (havingFilter.isConstantTrue()) {
+ havingFilter = null;
+ }
}
// EXPRESSION OVERRIDE HINTS
diff --git a/pinot-core/src/test/java/org/apache/pinot/core/query/request/context/utils/BrokerRequestToQueryContextConverterTest.java b/pinot-core/src/test/java/org/apache/pinot/core/query/request/context/utils/BrokerRequestToQueryContextConverterTest.java
index 866282478e..efeb7ac071 100644
--- a/pinot-core/src/test/java/org/apache/pinot/core/query/request/context/utils/BrokerRequestToQueryContextConverterTest.java
+++ b/pinot-core/src/test/java/org/apache/pinot/core/query/request/context/utils/BrokerRequestToQueryContextConverterTest.java
@@ -294,17 +294,17 @@ public class BrokerRequestToQueryContextConverterTest {
assertEquals(filter.getType(), FilterContext.Type.AND);
List<FilterContext> children = filter.getChildren();
assertEquals(children.size(), 2);
- assertEquals(children.get(0), new FilterContext(FilterContext.Type.PREDICATE, null,
+ assertEquals(children.get(0), FilterContext.forPredicate(
new RangePredicate(ExpressionContext.forIdentifier("foo"), false, "15", false, "*")));
FilterContext orFilter = children.get(1);
assertEquals(orFilter.getType(), FilterContext.Type.OR);
assertEquals(orFilter.getChildren().size(), 2);
- assertEquals(orFilter.getChildren().get(0), new FilterContext(FilterContext.Type.PREDICATE, null,
- new RangePredicate(ExpressionContext.forFunction(new FunctionContext(FunctionContext.Type.TRANSFORM, "div",
+ assertEquals(orFilter.getChildren().get(0), FilterContext.forPredicate(new RangePredicate(
+ ExpressionContext.forFunction(new FunctionContext(FunctionContext.Type.TRANSFORM, "div",
Arrays.asList(ExpressionContext.forIdentifier("bar"), ExpressionContext.forIdentifier("foo")))), true,
- "10", true, "20")));
- assertEquals(orFilter.getChildren().get(1), new FilterContext(FilterContext.Type.PREDICATE, null,
- new TextMatchPredicate(ExpressionContext.forIdentifier("foobar"), "potato")));
+ "10", true, "20")));
+ assertEquals(orFilter.getChildren().get(1),
+ FilterContext.forPredicate(new TextMatchPredicate(ExpressionContext.forIdentifier("foobar"), "potato")));
assertEquals(filter.toString(),
"(foo > '15' AND (div(bar,foo) BETWEEN '10' AND '20' OR text_match(foobar,'potato')))");
assertNull(queryContext.getGroupByExpressions());
@@ -340,7 +340,7 @@ public class BrokerRequestToQueryContextConverterTest {
assertEquals(aliasList.get(1), "b");
FilterContext filter = queryContext.getFilter();
assertNotNull(filter);
- assertEquals(filter, new FilterContext(FilterContext.Type.PREDICATE, null,
+ assertEquals(filter, FilterContext.forPredicate(
new InPredicate(ExpressionContext.forIdentifier("bar"), Arrays.asList("5", "10", "15"))));
assertEquals(filter.toString(), "bar IN ('5','10','15')");
List<ExpressionContext> groupByExpressions = queryContext.getGroupByExpressions();
@@ -388,8 +388,8 @@ public class BrokerRequestToQueryContextConverterTest {
assertNull(queryContext.getOrderByExpressions());
FilterContext havingFilter = queryContext.getHavingFilter();
assertNotNull(havingFilter);
- assertEquals(havingFilter, new FilterContext(FilterContext.Type.PREDICATE, null, new InPredicate(
- ExpressionContext.forFunction(new FunctionContext(FunctionContext.Type.AGGREGATION, "sum",
+ assertEquals(havingFilter, FilterContext.forPredicate(new InPredicate(ExpressionContext.forFunction(
+ new FunctionContext(FunctionContext.Type.AGGREGATION, "sum",
Collections.singletonList(ExpressionContext.forIdentifier("foo")))), Arrays.asList("5", "10", "15"))));
assertEquals(havingFilter.toString(), "sum(foo) IN ('5','10','15')");
assertEquals(queryContext.getLimit(), 10);
@@ -658,7 +658,7 @@ public class BrokerRequestToQueryContextConverterTest {
}
@Test
- void testDeduplicateOrderByExpressions() {
+ public void testDeduplicateOrderByExpressions() {
String query = "SELECT name FROM employees ORDER BY name DESC NULLS LAST, name ASC";
QueryContext queryContext = QueryContextConverterUtils.getQueryContext(query);
@@ -668,7 +668,7 @@ public class BrokerRequestToQueryContextConverterTest {
}
@Test
- void testRemoveOrderByFunctions() {
+ public void testRemoveOrderByFunctions() {
String query = "SELECT A FROM testTable ORDER BY datetrunc(A) DESC NULLS LAST";
QueryContext queryContext = QueryContextConverterUtils.getQueryContext(query);
@@ -684,7 +684,7 @@ public class BrokerRequestToQueryContextConverterTest {
}
@Test
- void testOrderByDefault() {
+ public void testOrderByDefault() {
String query = "SELECT A FROM testTable ORDER BY A";
QueryContext queryContext = QueryContextConverterUtils.getQueryContext(query);
@@ -698,7 +698,7 @@ public class BrokerRequestToQueryContextConverterTest {
}
@Test
- void testOrderByNullsLast() {
+ public void testOrderByNullsLast() {
String query = "SELECT A FROM testTable ORDER BY A NULLS LAST";
QueryContext queryContext = QueryContextConverterUtils.getQueryContext(query);
@@ -712,7 +712,7 @@ public class BrokerRequestToQueryContextConverterTest {
}
@Test
- void testOrderByNullsFirst() {
+ public void testOrderByNullsFirst() {
String query = "SELECT A FROM testTable ORDER BY A NULLS FIRST";
QueryContext queryContext = QueryContextConverterUtils.getQueryContext(query);
@@ -726,7 +726,7 @@ public class BrokerRequestToQueryContextConverterTest {
}
@Test
- void testOrderByAscNullsFirst() {
+ public void testOrderByAscNullsFirst() {
String query = "SELECT A FROM testTable ORDER BY A ASC NULLS FIRST";
QueryContext queryContext = QueryContextConverterUtils.getQueryContext(query);
@@ -740,7 +740,7 @@ public class BrokerRequestToQueryContextConverterTest {
}
@Test
- void testOrderByAscNullsLast() {
+ public void testOrderByAscNullsLast() {
String query = "SELECT A FROM testTable ORDER BY A ASC NULLS LAST";
QueryContext queryContext = QueryContextConverterUtils.getQueryContext(query);
@@ -754,7 +754,7 @@ public class BrokerRequestToQueryContextConverterTest {
}
@Test
- void testOrderByDescNullsFirst() {
+ public void testOrderByDescNullsFirst() {
String query = "SELECT A FROM testTable ORDER BY A DESC NULLS FIRST";
QueryContext queryContext = QueryContextConverterUtils.getQueryContext(query);
@@ -768,7 +768,7 @@ public class BrokerRequestToQueryContextConverterTest {
}
@Test
- void testOrderByDescNullsLast() {
+ public void testOrderByDescNullsLast() {
String query = "SELECT A FROM testTable ORDER BY A DESC NULLS LAST";
QueryContext queryContext = QueryContextConverterUtils.getQueryContext(query);
@@ -782,7 +782,7 @@ public class BrokerRequestToQueryContextConverterTest {
}
@Test
- void testDistinctOrderByNullsLast() {
+ public void testDistinctOrderByNullsLast() {
String query = "SELECT DISTINCT A FROM testTable ORDER BY A NULLS LAST";
QueryContext queryContext = QueryContextConverterUtils.getQueryContext(query);
@@ -794,4 +794,55 @@ public class BrokerRequestToQueryContextConverterTest {
assertTrue(orderByExpressionContext.isAsc());
assertTrue(orderByExpressionContext.isNullsLast());
}
+
+ @Test
+ public void testConstantFilter() {
+ String query = "SELECT * FROM testTable WHERE true";
+ QueryContext queryContext = QueryContextConverterUtils.getQueryContext(query);
+ assertNull(queryContext.getFilter());
+
+ query = "SELECT * FROM testTable WHERE false";
+ queryContext = QueryContextConverterUtils.getQueryContext(query);
+ assertSame(queryContext.getFilter(), FilterContext.CONSTANT_FALSE);
+
+ query = "SELECT * FROM testTable WHERE 'true'";
+ queryContext = QueryContextConverterUtils.getQueryContext(query);
+ assertNull(queryContext.getFilter());
+
+ query = "SELECT * FROM testTable WHERE 'false'";
+ queryContext = QueryContextConverterUtils.getQueryContext(query);
+ assertSame(queryContext.getFilter(), FilterContext.CONSTANT_FALSE);
+
+ query = "SELECT * FROM testTable WHERE 1 = 1";
+ queryContext = QueryContextConverterUtils.getQueryContext(query);
+ assertNull(queryContext.getFilter());
+
+ query = "SELECT * FROM testTable WHERE 1 = 0";
+ queryContext = QueryContextConverterUtils.getQueryContext(query);
+ assertSame(queryContext.getFilter(), FilterContext.CONSTANT_FALSE);
+
+ query = "SELECT * FROM testTable WHERE 1 = 1 AND 2 = 2";
+ queryContext = QueryContextConverterUtils.getQueryContext(query);
+ assertNull(queryContext.getFilter());
+
+ query = "SELECT * FROM testTable WHERE 1 = 1 AND 2 = 3";
+ queryContext = QueryContextConverterUtils.getQueryContext(query);
+ assertSame(queryContext.getFilter(), FilterContext.CONSTANT_FALSE);
+
+ query = "SELECT * FROM testTable WHERE 1 = 1 OR 2 = 3";
+ queryContext = QueryContextConverterUtils.getQueryContext(query);
+ assertNull(queryContext.getFilter());
+
+ query = "SELECT * FROM testTable WHERE 1 = 0 OR 2 = 3";
+ queryContext = QueryContextConverterUtils.getQueryContext(query);
+ assertSame(queryContext.getFilter(), FilterContext.CONSTANT_FALSE);
+
+ query = "SELECT * FROM testTable WHERE NOT 1 = 1";
+ queryContext = QueryContextConverterUtils.getQueryContext(query);
+ assertSame(queryContext.getFilter(), FilterContext.CONSTANT_FALSE);
+
+ query = "SELECT * FROM testTable WHERE NOT 1 = 0";
+ queryContext = QueryContextConverterUtils.getQueryContext(query);
+ assertNull(queryContext.getFilter());
+ }
}
diff --git a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/realtime/impl/json/MutableJsonIndexImpl.java b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/realtime/impl/json/MutableJsonIndexImpl.java
index afa73f0a3a..46e7798204 100644
--- a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/realtime/impl/json/MutableJsonIndexImpl.java
+++ b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/realtime/impl/json/MutableJsonIndexImpl.java
@@ -120,6 +120,7 @@ public class MutableJsonIndexImpl implements MutableJsonIndex {
FilterContext filter;
try {
filter = RequestContextUtils.getFilter(CalciteSqlParser.compileToExpression(filterString));
+ Preconditions.checkArgument(!filter.isConstant());
} catch (Exception e) {
throw new BadQueryRequestException("Invalid json match filter: " + filterString);
}
diff --git a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/readers/json/ImmutableJsonIndexReader.java b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/readers/json/ImmutableJsonIndexReader.java
index 757053e323..ac4a24d56d 100644
--- a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/readers/json/ImmutableJsonIndexReader.java
+++ b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/readers/json/ImmutableJsonIndexReader.java
@@ -86,6 +86,7 @@ public class ImmutableJsonIndexReader implements JsonIndexReader {
FilterContext filter;
try {
filter = RequestContextUtils.getFilter(CalciteSqlParser.compileToExpression(filterString));
+ Preconditions.checkArgument(!filter.isConstant());
} catch (Exception e) {
throw new BadQueryRequestException("Invalid json match filter: " + filterString);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org