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 f342684645 [Feature] [Refactoring] Create LiteralContext to hold type
and value of literal and Boolean literal eval support (#9389)
f342684645 is described below
commit f34268464548126f56aa00936786e4d0ea1977fd
Author: Yao Liu <[email protected]>
AuthorDate: Thu Oct 6 11:21:17 2022 -0700
[Feature] [Refactoring] Create LiteralContext to hold type and value of
literal and Boolean literal eval support (#9389)
Features added
1. Pass the literal for boolean as the correct type from thrift.
2. Only boolean literal and some numerical types are supported.
3. This naturally fixes the boolean literal eval because we have a query
rewrite for this.
Follow up
- Literal toString is still returning a single-quoted version for backward
compatibility. However, in order to maintain backward compatibility, this
format cannot be changed.
- Many APIs are still relying on the toString method, we can modify them
later to use the value accessor.
- Adding other Literal type support that cannot be directly expressed in
SQL semantics, but can be produced after the compiled-time ScalarFunction
evaluator preprocessed the value.
---
.../common/request/context/ExpressionContext.java | 61 +++++++---
.../common/request/context/LiteralContext.java | 124 +++++++++++++++++++++
.../request/context/RequestContextUtils.java | 6 +-
.../pinot/common/utils/request/RequestUtils.java | 14 ++-
.../pinot/sql/parsers/CalciteSqlCompilerTest.java | 10 +-
.../apache/pinot/core/data/table/TableResizer.java | 2 +-
.../filter/H3InclusionIndexFilterOperator.java | 4 +-
.../operator/filter/H3IndexFilterOperator.java | 6 +-
.../function/LiteralTransformFunction.java | 42 +++----
.../function/AggregationFunctionFactory.java | 7 +-
.../DistinctCountHLLAggregationFunction.java | 2 +-
.../DistinctCountSmartHLLAggregationFunction.java | 2 +-
...istinctCountThetaSketchAggregationFunction.java | 13 ++-
.../function/HistogramAggregationFunction.java | 13 ++-
.../function/IdSetAggregationFunction.java | 2 +-
.../function/ModeAggregationFunction.java | 2 +-
.../PercentileSmartTDigestAggregationFunction.java | 4 +-
.../function/SumPrecisionAggregationFunction.java | 4 +-
.../query/executor/ServerQueryExecutorV1Impl.java | 9 +-
.../core/query/reduce/BaseGapfillProcessor.java | 12 +-
.../core/query/reduce/GapfillFilterHandler.java | 2 +-
.../pinot/core/query/reduce/GapfillProcessor.java | 4 +-
.../core/query/reduce/PostAggregationHandler.java | 2 +-
.../core/query/reduce/SumAvgGapfillProcessor.java | 2 +-
.../org/apache/pinot/core/util/GapfillUtils.java | 3 +-
.../function/LiteralTransformFunctionTest.java | 9 +-
.../plan/maker/QueryOverrideWithHintsTest.java | 52 +++++----
.../BrokerRequestToQueryContextConverterTest.java | 31 ++++--
.../tests/OfflineClusterIntegrationTest.java | 33 ++++++
.../query/runtime/operator/AggregateOperator.java | 2 +-
.../local/function/InbuiltFunctionEvaluator.java | 3 +-
.../indexsegment/mutable/MutableSegmentImpl.java | 2 +-
32 files changed, 362 insertions(+), 122 deletions(-)
diff --git
a/pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
b/pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
index 141c396eb2..daf586e4a7 100644
---
a/pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
+++
b/pinot-common/src/main/java/org/apache/pinot/common/request/context/ExpressionContext.java
@@ -20,6 +20,8 @@ package org.apache.pinot.common.request.context;
import java.util.Objects;
import java.util.Set;
+import org.apache.pinot.common.request.Literal;
+import org.apache.pinot.spi.data.FieldSpec;
/**
@@ -35,37 +37,54 @@ public class ExpressionContext {
}
private final Type _type;
- private final String _value;
+ private final String _identifier;
private final FunctionContext _function;
+ // Only set when the _type is LITERAL
+ private final LiteralContext _literal;
- public static ExpressionContext forLiteral(String literal) {
- return new ExpressionContext(Type.LITERAL, literal, null);
+ public static ExpressionContext forLiteralContext(Literal literal) {
+ return new ExpressionContext(Type.LITERAL, null, null, new
LiteralContext(literal));
+ }
+
+ public static ExpressionContext forLiteralContext(FieldSpec.DataType type,
Object val) {
+ return new ExpressionContext(Type.LITERAL, null, null, new
LiteralContext(type, val));
}
public static ExpressionContext forIdentifier(String identifier) {
- return new ExpressionContext(Type.IDENTIFIER, identifier, null);
+ return new ExpressionContext(Type.IDENTIFIER, identifier, null, null);
}
public static ExpressionContext forFunction(FunctionContext function) {
- return new ExpressionContext(Type.FUNCTION, null, function);
+ return new ExpressionContext(Type.FUNCTION, null, function, null);
}
- private ExpressionContext(Type type, String value, FunctionContext function)
{
+ private ExpressionContext(Type type, String identifier, FunctionContext
function, LiteralContext literal) {
_type = type;
- _value = value;
+ _identifier = identifier;
_function = function;
+ _literal = literal;
+ }
+
+ // TODO: Refactor all of the usage for getLiteralString.
+ @Deprecated
+ public String getLiteralString() {
+ if (_literal == null || _literal.getValue() == null) {
+ return null;
+ }
+ return _literal.getValue().toString();
}
public Type getType() {
return _type;
}
- public String getLiteral() {
- return _value;
+ // Please check the _type of this context is Literal before calling get,
otherwise it may return null.
+ public LiteralContext getLiteral(){
+ return _literal;
}
public String getIdentifier() {
- return _value;
+ return _identifier;
}
public FunctionContext getFunction() {
@@ -77,8 +96,8 @@ public class ExpressionContext {
*/
public void getColumns(Set<String> columns) {
if (_type == Type.IDENTIFIER) {
- if (!_value.equals("*")) {
- columns.add(_value);
+ if (!_identifier.equals("*")) {
+ columns.add(_identifier);
}
} else if (_type == Type.FUNCTION) {
_function.getColumns(columns);
@@ -94,25 +113,31 @@ public class ExpressionContext {
return false;
}
ExpressionContext that = (ExpressionContext) o;
- return _type == that._type && Objects.equals(_value, that._value) &&
Objects.equals(_function, that._function);
+ return _type == that._type && Objects.equals(_identifier,
that._identifier) && Objects.equals(_function, that._function) &&
Objects.equals(_literal, that._literal);
}
@Override
public int hashCode() {
int hash = 31 * 31 * _type.hashCode();
- if (_type == Type.FUNCTION) {
- return hash + _function.hashCode();
+ switch (_type) {
+ case LITERAL:
+ return hash + _literal.hashCode();
+ case IDENTIFIER:
+ return hash + _identifier.hashCode();
+ case FUNCTION:
+ return hash + _function.hashCode();
+ default:
+ throw new IllegalStateException();
}
- return hash + 31 * _value.hashCode();
}
@Override
public String toString() {
switch (_type) {
case LITERAL:
- return '\'' + _value + '\'';
+ return _literal.toString();
case IDENTIFIER:
- return _value;
+ return _identifier;
case FUNCTION:
return _function.toString();
default:
diff --git
a/pinot-common/src/main/java/org/apache/pinot/common/request/context/LiteralContext.java
b/pinot-common/src/main/java/org/apache/pinot/common/request/context/LiteralContext.java
new file mode 100644
index 0000000000..e8e00a5330
--- /dev/null
+++
b/pinot-common/src/main/java/org/apache/pinot/common/request/context/LiteralContext.java
@@ -0,0 +1,124 @@
+/**
+ * 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.common.request.context;
+
+import com.google.common.base.Preconditions;
+import java.util.Objects;
+import javax.annotation.Nullable;
+import org.apache.pinot.common.request.Literal;
+import org.apache.pinot.spi.data.FieldSpec;
+
+
+/**
+ * The {@code LiteralContext} class represents a literal in the query.
+ * <p>This includes both value and type information. We translate thrift
literal to this representation in server.
+ * Currently, only Boolean literal is correctly encoded in thrift and passed
in.
+ * All integers are encoded as LONG in thrift, and the other numerical types
are encoded as DOUBLE.
+ * The remaining types are encoded as STRING.
+ */
+public class LiteralContext {
+ // TODO: Support all of the types for sql.
+ private FieldSpec.DataType _type;
+ private Object _value;
+
+ // TODO: Support all data types.
+ private static FieldSpec.DataType
convertThriftTypeToDataType(Literal._Fields fields) {
+ switch (fields) {
+ case LONG_VALUE:
+ return FieldSpec.DataType.LONG;
+ case BOOL_VALUE:
+ return FieldSpec.DataType.BOOLEAN;
+ case DOUBLE_VALUE:
+ return FieldSpec.DataType.DOUBLE;
+ case STRING_VALUE:
+ return FieldSpec.DataType.STRING;
+ default:
+ throw new UnsupportedOperationException("Unsupported literal type:" +
fields);
+ }
+ }
+
+ private static Class<?> convertDataTypeToJavaType(FieldSpec.DataType
dataType) {
+ switch (dataType) {
+ case INT:
+ return Integer.class;
+ case LONG:
+ return Long.class;
+ case BOOLEAN:
+ return Boolean.class;
+ case FLOAT:
+ return Float.class;
+ case DOUBLE:
+ return Double.class;
+ case STRING:
+ return String.class;
+ default:
+ throw new UnsupportedOperationException("Unsupported dataType:" +
dataType);
+ }
+ }
+
+ public LiteralContext(Literal literal) {
+ _type = convertThriftTypeToDataType(literal.getSetField());
+ _value = literal.getFieldValue();
+ }
+
+ public FieldSpec.DataType getType() {
+ return _type;
+ }
+
+ @Nullable
+ public Object getValue() {
+ return _value;
+ }
+
+ public LiteralContext(FieldSpec.DataType type, Object value) {
+ Preconditions.checkArgument(convertDataTypeToJavaType(type) ==
value.getClass(),
+ "Unmatched data type: " + type + " java type: " + value.getClass());
+ _type = type;
+ _value = value;
+ }
+
+ @Override
+ public int hashCode() {
+ if (_value == null) {
+ return 31 * _type.hashCode();
+ }
+ return 31 * _value.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof LiteralContext)) {
+ return false;
+ }
+ LiteralContext that = (LiteralContext) o;
+ return _type.equals(that._type) && Objects.equals(_value, that._value);
+ }
+
+ @Override
+ public String toString() {
+ if (_value == null) {
+ return "null";
+ }
+ // TODO: print out the type.
+ return '\'' + _value.toString() + '\'';
+ }
+}
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 97668db6a9..ad2340942f 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
@@ -66,7 +66,7 @@ public class RequestContextUtils {
public static ExpressionContext getExpression(Expression thriftExpression) {
switch (thriftExpression.getType()) {
case LITERAL:
- return
ExpressionContext.forLiteral(thriftExpression.getLiteral().getFieldValue().toString());
+ return
ExpressionContext.forLiteralContext(thriftExpression.getLiteral());
case IDENTIFIER:
return
ExpressionContext.forIdentifier(thriftExpression.getIdentifier().getName());
case FUNCTION:
@@ -352,10 +352,10 @@ public class RequestContextUtils {
}
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");
}
- return expressionContext.getLiteral();
+ return expressionContext.getLiteralString();
}
}
diff --git
a/pinot-common/src/main/java/org/apache/pinot/common/utils/request/RequestUtils.java
b/pinot-common/src/main/java/org/apache/pinot/common/utils/request/RequestUtils.java
index 3da9b4cb21..deb26491b1 100644
---
a/pinot-common/src/main/java/org/apache/pinot/common/utils/request/RequestUtils.java
+++
b/pinot-common/src/main/java/org/apache/pinot/common/utils/request/RequestUtils.java
@@ -104,6 +104,7 @@ public class RequestUtils {
Expression expression = new Expression(ExpressionType.LITERAL);
Literal literal = new Literal();
if (node instanceof SqlNumericLiteral) {
+ // TODO: support different integer and floating point type.
// Mitigate calcite NPE bug, we need to check if
SqlNumericLiteral.getScale() is null before calling
// SqlNumericLiteral.isInteger(). TODO: Undo this fix once a Calcite
release that contains CALCITE-4199 is
// available and Pinot has been upgraded to use such a release.
@@ -114,7 +115,15 @@ public class RequestUtils {
literal.setDoubleValue(node.bigDecimalValue().doubleValue());
}
} else {
- literal.setStringValue(StringUtils.replace(node.toValue(), "''", "'"));
+ // TODO: Support null literal and other types.
+ switch (node.getTypeName()) {
+ case BOOLEAN:
+ literal.setBoolValue(node.booleanValue());
+ break;
+ default:
+ literal.setStringValue(StringUtils.replace(node.toValue(), "''",
"'"));
+ break;
+ }
}
expression.setLiteral(literal);
return expression;
@@ -167,6 +176,9 @@ public class RequestUtils {
if (object instanceof byte[]) {
return RequestUtils.getLiteralExpression((byte[]) object);
}
+ if (object instanceof Boolean) {
+ return RequestUtils.getLiteralExpression(((Boolean)
object).booleanValue());
+ }
return RequestUtils.getLiteralExpression(object.toString());
}
diff --git
a/pinot-common/src/test/java/org/apache/pinot/sql/parsers/CalciteSqlCompilerTest.java
b/pinot-common/src/test/java/org/apache/pinot/sql/parsers/CalciteSqlCompilerTest.java
index c662af0468..901cc4860a 100644
---
a/pinot-common/src/test/java/org/apache/pinot/sql/parsers/CalciteSqlCompilerTest.java
+++
b/pinot-common/src/test/java/org/apache/pinot/sql/parsers/CalciteSqlCompilerTest.java
@@ -301,7 +301,7 @@ public class CalciteSqlCompilerTest {
Assert.assertEquals(eqOperands.get(1).getLiteral(),
Literal.boolValue(true));
eqOperands = operands.get(1).getFunctionCall().getOperands();
Assert.assertEquals(eqOperands.get(0).getIdentifier().getName(), "f");
- Assert.assertEquals(eqOperands.get(1).getLiteral(),
Literal.stringValue("true"));
+ Assert.assertEquals(eqOperands.get(1).getLiteral(),
Literal.boolValue(true));
}
{
@@ -324,7 +324,7 @@ public class CalciteSqlCompilerTest {
Assert.assertEquals(operands.get(0).getFunctionCall().getOperator(),
FilterKind.EQUALS.name());
List<Expression> eqOperands =
operands.get(0).getFunctionCall().getOperands();
Assert.assertEquals(eqOperands.get(0).getFunctionCall().getOperator(),
"startswith");
- Assert.assertEquals(eqOperands.get(1).getLiteral(),
Literal.stringValue("true"));
+ Assert.assertEquals(eqOperands.get(1).getLiteral(),
Literal.boolValue(true));
Assert.assertEquals(operands.get(1).getFunctionCall().getOperator(),
FilterKind.EQUALS.name());
eqOperands = operands.get(1).getFunctionCall().getOperands();
@@ -343,7 +343,7 @@ public class CalciteSqlCompilerTest {
Assert.assertEquals(operands.get(0).getFunctionCall().getOperator(),
FilterKind.EQUALS.name());
List<Expression> eqOperands =
operands.get(0).getFunctionCall().getOperands();
Assert.assertEquals(eqOperands.get(0).getFunctionCall().getOperator(),
"startswith");
- Assert.assertEquals(eqOperands.get(1).getLiteral(),
Literal.stringValue("true"));
+ Assert.assertEquals(eqOperands.get(1).getLiteral(),
Literal.boolValue(true));
Assert.assertEquals(operands.get(1).getFunctionCall().getOperator(),
FilterKind.EQUALS.name());
eqOperands = operands.get(1).getFunctionCall().getOperands();
@@ -358,7 +358,7 @@ public class CalciteSqlCompilerTest {
Assert.assertEquals(operands.get(3).getFunctionCall().getOperator(),
FilterKind.EQUALS.name());
eqOperands = operands.get(3).getFunctionCall().getOperands();
Assert.assertEquals(eqOperands.get(0).getIdentifier().getName(), "d");
- Assert.assertEquals(eqOperands.get(1).getLiteral(),
Literal.stringValue("true"));
+ Assert.assertEquals(eqOperands.get(1).getLiteral(),
Literal.boolValue(true));
}
}
@@ -2325,7 +2325,7 @@ public class CalciteSqlCompilerTest {
Assert.assertEquals(operands.get(3).getFunctionCall().getOperator(),
FilterKind.EQUALS.name());
eqOperands = operands.get(3).getFunctionCall().getOperands();
Assert.assertEquals(eqOperands.get(0).getIdentifier(), new
Identifier("col4"));
- Assert.assertEquals(eqOperands.get(1).getLiteral(),
Literal.stringValue("true"));
+ Assert.assertEquals(eqOperands.get(1).getLiteral(),
Literal.boolValue(true));
}
{
String query = "SELECT * FROM foo WHERE col1 <= 0 OR col2 <= 0 OR (col3
<= 0 OR col4 <= 0)";
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/data/table/TableResizer.java
b/pinot-core/src/main/java/org/apache/pinot/core/data/table/TableResizer.java
index 392849df37..7f6704fd7a 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/data/table/TableResizer.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/data/table/TableResizer.java
@@ -124,7 +124,7 @@ public class TableResizer {
*/
private OrderByValueExtractor getOrderByValueExtractor(ExpressionContext
expression) {
if (expression.getType() == ExpressionContext.Type.LITERAL) {
- return new LiteralExtractor(expression.getLiteral());
+ return new LiteralExtractor(expression.getLiteralString());
}
Integer groupByExpressionIndex =
_groupByExpressionIndexMap.get(expression);
if (groupByExpressionIndex != null) {
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/H3InclusionIndexFilterOperator.java
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/H3InclusionIndexFilterOperator.java
index 3b0e8280bd..081afdf271 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/H3InclusionIndexFilterOperator.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/H3InclusionIndexFilterOperator.java
@@ -72,10 +72,10 @@ public class H3InclusionIndexFilterOperator extends
BaseFilterOperator {
if (arguments.get(0).getType() == ExpressionContext.Type.IDENTIFIER) {
_h3IndexReader =
segment.getDataSource(arguments.get(0).getIdentifier()).getH3Index();
- _geometry =
GeometrySerializer.deserialize(BytesUtils.toBytes(arguments.get(1).getLiteral()));
+ _geometry =
GeometrySerializer.deserialize(BytesUtils.toBytes(arguments.get(1).getLiteralString()));
} else {
_h3IndexReader =
segment.getDataSource(arguments.get(1).getIdentifier()).getH3Index();
- _geometry =
GeometrySerializer.deserialize(BytesUtils.toBytes(arguments.get(0).getLiteral()));
+ _geometry =
GeometrySerializer.deserialize(BytesUtils.toBytes(arguments.get(0).getLiteralString()));
}
// must be some h3 index
assert _h3IndexReader != null : "the column must have H3 index setup.";
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/H3IndexFilterOperator.java
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/H3IndexFilterOperator.java
index 09ce51597b..9f91127c12 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/H3IndexFilterOperator.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/operator/filter/H3IndexFilterOperator.java
@@ -67,10 +67,12 @@ public class H3IndexFilterOperator extends
BaseFilterOperator {
Coordinate coordinate;
if (arguments.get(0).getType() == ExpressionContext.Type.IDENTIFIER) {
_h3IndexReader =
segment.getDataSource(arguments.get(0).getIdentifier()).getH3Index();
- coordinate =
GeometrySerializer.deserialize(BytesUtils.toBytes(arguments.get(1).getLiteral())).getCoordinate();
+ coordinate =
+
GeometrySerializer.deserialize(BytesUtils.toBytes(arguments.get(1).getLiteralString())).getCoordinate();
} else {
_h3IndexReader =
segment.getDataSource(arguments.get(1).getIdentifier()).getH3Index();
- coordinate =
GeometrySerializer.deserialize(BytesUtils.toBytes(arguments.get(0).getLiteral())).getCoordinate();
+ coordinate =
+
GeometrySerializer.deserialize(BytesUtils.toBytes(arguments.get(0).getLiteralString())).getCoordinate();
}
assert _h3IndexReader != null;
int resolution =
_h3IndexReader.getH3IndexResolution().getLowestResolution();
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/LiteralTransformFunction.java
b/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/LiteralTransformFunction.java
index 5f562fccd7..dc63437f36 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/LiteralTransformFunction.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/operator/transform/function/LiteralTransformFunction.java
@@ -19,6 +19,7 @@
package org.apache.pinot.core.operator.transform.function;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
@@ -26,6 +27,7 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.math.NumberUtils;
+import org.apache.pinot.common.request.context.LiteralContext;
import org.apache.pinot.common.utils.PinotDataType;
import org.apache.pinot.core.operator.blocks.ProjectionBlock;
import org.apache.pinot.core.operator.transform.TransformResultMetadata;
@@ -41,6 +43,7 @@ import org.apache.pinot.spi.utils.BytesUtils;
* TODO: Preserve the type of the literal instead of inferring the type from
the string
*/
public class LiteralTransformFunction implements TransformFunction {
+ // TODO: Deprecate the string representation of literal.
private final String _literal;
private final DataType _dataType;
private final int _intLiteral;
@@ -58,27 +61,31 @@ public class LiteralTransformFunction implements
TransformFunction {
private String[] _stringResult;
private byte[][] _bytesResult;
- public LiteralTransformFunction(String literal) {
- _literal = literal;
- _dataType = inferLiteralDataType(literal);
- if (_dataType.isNumeric()) {
- _bigDecimalLiteral = new BigDecimal(_literal);
- } else if (_dataType == DataType.BOOLEAN) {
- _bigDecimalLiteral =
PinotDataType.BOOLEAN.toBigDecimal(Boolean.valueOf(literal));
- } else if (_dataType == DataType.TIMESTAMP) {
- // inferLiteralDataType successfully interpreted the literal as
TIMESTAMP. _bigDecimalLiteral is populated and
- // assigned to _longLiteral.
- _bigDecimalLiteral =
PinotDataType.TIMESTAMP.toBigDecimal(Timestamp.valueOf(literal));
+ public LiteralTransformFunction(LiteralContext literalContext) {
+ Preconditions.checkNotNull(literalContext);
+ _literal = literalContext.getValue() == null ? "" :
literalContext.getValue().toString();
+ if (literalContext.getType() == DataType.BOOLEAN) {
+ _bigDecimalLiteral =
PinotDataType.BOOLEAN.toBigDecimal(literalContext.getValue());
+ _dataType = DataType.BOOLEAN;
} else {
- _bigDecimalLiteral = BigDecimal.ZERO;
+ _dataType = inferLiteralDataType(_literal);
+ if (_dataType.isNumeric()) {
+ _bigDecimalLiteral = new BigDecimal(_literal);
+ } else if (_dataType == DataType.TIMESTAMP) {
+ // inferLiteralDataType successfully interpreted the literal as
TIMESTAMP. _bigDecimalLiteral is populated and
+ // assigned to _longLiteral.
+ _bigDecimalLiteral =
PinotDataType.TIMESTAMP.toBigDecimal(Timestamp.valueOf(_literal));
+ } else {
+ _bigDecimalLiteral = BigDecimal.ZERO;
+ }
}
-
_intLiteral = _bigDecimalLiteral.intValue();
_longLiteral = _bigDecimalLiteral.longValue();
_floatLiteral = _bigDecimalLiteral.floatValue();
_doubleLiteral = _bigDecimalLiteral.doubleValue();
}
+ // TODO: Deprecate the usage case for this function.
@VisibleForTesting
static DataType inferLiteralDataType(String literal) {
// Try to interpret the literal as number
@@ -101,13 +108,6 @@ public class LiteralTransformFunction implements
TransformFunction {
// Ignored
}
- // Try to interpret the literal as BOOLEAN
- // NOTE: Intentionally use equals() instead of equalsIgnoreCase() here
because boolean literal will always be parsed
- // into lowercase string. We don't want to parse string "TRUE" as
boolean.
- if (literal.equals("true") || literal.equals("false")) {
- return DataType.BOOLEAN;
- }
-
// Try to interpret the literal as TIMESTAMP
try {
Timestamp.valueOf(literal);
@@ -163,7 +163,7 @@ public class LiteralTransformFunction implements
TransformFunction {
Arrays.fill(intResult, _intLiteral);
}
} else {
- Arrays.fill(intResult, _literal.equals("true") ? 1 : 0);
+ Arrays.fill(intResult, _intLiteral);
}
_intResult = intResult;
}
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/AggregationFunctionFactory.java
b/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/AggregationFunctionFactory.java
index 409b21dd57..3eb3a4f5ad 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/AggregationFunctionFactory.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/AggregationFunctionFactory.java
@@ -101,7 +101,8 @@ public class AggregationFunctionFactory {
} else if (numArguments == 2) {
// Double arguments percentile (e.g. percentile(foo, 99),
percentileTDigest(bar, 95), etc.) where the
// second argument is a decimal number from 0.0 to 100.0.
- double percentile =
parsePercentileToDouble(arguments.get(1).getLiteral());
+ // Have to use literal string because we need to cast int to double
here.
+ double percentile =
parsePercentileToDouble(arguments.get(1).getLiteralString());
if (remainingFunctionName.isEmpty()) {
// Percentile
return new PercentileAggregationFunction(firstArgument,
percentile);
@@ -169,7 +170,7 @@ public class AggregationFunctionFactory {
+ " The function can be used as firstWithTime(dataColumn,
timeColumn, 'dataType')");
}
FieldSpec.DataType fieldDataType
- =
FieldSpec.DataType.valueOf(dataType.getLiteral().toUpperCase());
+ =
FieldSpec.DataType.valueOf(dataType.getLiteralString().toUpperCase());
switch (fieldDataType) {
case BOOLEAN:
case INT:
@@ -198,7 +199,7 @@ public class AggregationFunctionFactory {
throw new IllegalArgumentException("Third argument of
lastWithTime Function should be literal."
+ " The function can be used as lastWithTime(dataColumn,
timeColumn, 'dataType')");
}
- FieldSpec.DataType fieldDataType =
FieldSpec.DataType.valueOf(dataType.getLiteral().toUpperCase());
+ FieldSpec.DataType fieldDataType =
FieldSpec.DataType.valueOf(dataType.getLiteralString().toUpperCase());
switch (fieldDataType) {
case BOOLEAN:
case INT:
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/DistinctCountHLLAggregationFunction.java
b/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/DistinctCountHLLAggregationFunction.java
index d928585279..914177ae8c 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/DistinctCountHLLAggregationFunction.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/DistinctCountHLLAggregationFunction.java
@@ -48,7 +48,7 @@ public class DistinctCountHLLAggregationFunction extends
BaseSingleInputAggregat
Preconditions.checkArgument(numExpressions <= 2, "DistinctCountHLL expects
1 or 2 arguments, got: %s",
numExpressions);
if (arguments.size() == 2) {
- _log2m = Integer.parseInt(arguments.get(1).getLiteral());
+ _log2m = Integer.parseInt(arguments.get(1).getLiteralString());
} else {
_log2m = CommonConstants.Helix.DEFAULT_HYPERLOGLOG_LOG2M;
}
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/DistinctCountSmartHLLAggregationFunction.java
b/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/DistinctCountSmartHLLAggregationFunction.java
index 2ee2e85545..87e418f935 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/DistinctCountSmartHLLAggregationFunction.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/DistinctCountSmartHLLAggregationFunction.java
@@ -68,7 +68,7 @@ public class DistinctCountSmartHLLAggregationFunction extends
BaseSingleInputAgg
super(arguments.get(0));
if (arguments.size() > 1) {
- Parameters parameters = new Parameters(arguments.get(1).getLiteral());
+ Parameters parameters = new
Parameters(arguments.get(1).getLiteralString());
_threshold = parameters._threshold;
_log2m = parameters._log2m;
} else {
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 a371bf237e..317cb48693 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
@@ -34,6 +34,7 @@ import org.apache.datasketches.theta.Sketch;
import org.apache.datasketches.theta.Union;
import org.apache.datasketches.theta.UpdateSketch;
import org.apache.datasketches.theta.UpdateSketchBuilder;
+import org.apache.pinot.common.request.Expression;
import org.apache.pinot.common.request.context.ExpressionContext;
import org.apache.pinot.common.request.context.FilterContext;
import org.apache.pinot.common.request.context.FunctionContext;
@@ -100,7 +101,7 @@ public class DistinctCountThetaSketchAggregationFunction
ExpressionContext paramsExpression = arguments.get(1);
Preconditions.checkArgument(paramsExpression.getType() ==
ExpressionContext.Type.LITERAL,
"Second argument of DISTINCT_COUNT_THETA_SKETCH aggregation function
must be literal (parameters)");
- Parameters parameters = new Parameters(paramsExpression.getLiteral());
+ Parameters parameters = new
Parameters(paramsExpression.getLiteralString());
int nominalEntries = parameters.getNominalEntries();
_updateSketchBuilder.setNominalEntries(nominalEntries);
_setOperationBuilder.setNominalEntries(nominalEntries);
@@ -130,7 +131,7 @@ public class DistinctCountThetaSketchAggregationFunction
"Third to second last argument of DISTINCT_COUNT_THETA_SKETCH
aggregation function must be literal "
+ "(filter expression)");
FilterContext filter =
-
RequestContextUtils.getFilter(CalciteSqlParser.compileToExpression(filterExpression.getLiteral()));
+
RequestContextUtils.getFilter(CalciteSqlParser.compileToExpression(filterExpression.getLiteralString()));
// NOTE: Collect expressions before constructing the FilterInfo so
that expressionIndexMap always include the
// expressions in the filter.
collectExpressions(filter, _inputExpressions, expressionIndexMap);
@@ -142,8 +143,9 @@ public class DistinctCountThetaSketchAggregationFunction
Preconditions.checkArgument(postAggregationExpression.getType() ==
ExpressionContext.Type.LITERAL,
"Last argument of DISTINCT_COUNT_THETA_SKETCH aggregation function
must be literal (post-aggregation "
+ "expression)");
- _postAggregationExpression = RequestContextUtils.getExpression(
-
CalciteSqlParser.compileToExpression(postAggregationExpression.getLiteral()));
+ Expression expr =
CalciteSqlParser.compileToExpression(postAggregationExpression.getLiteralString());
+ _postAggregationExpression = RequestContextUtils.getExpression(expr);
+
// Validate the post-aggregation expression
_includeDefaultSketch =
validatePostAggregationExpression(_postAggregationExpression,
_filterEvaluators.size());
@@ -1051,8 +1053,7 @@ public class DistinctCountThetaSketchAggregationFunction
*/
private static boolean validatePostAggregationExpression(ExpressionContext
expression, int numFilters) {
Preconditions.checkArgument(expression.getType() !=
ExpressionContext.Type.LITERAL,
- "Post-aggregation expression should not contain literal expression:
%s", expression.getLiteral());
-
+ "Post-aggregation expression should not contain literal expression:
%s", expression.toString());
if (expression.getType() == ExpressionContext.Type.IDENTIFIER) {
int sketchId = extractSketchId(expression.getIdentifier());
Preconditions.checkArgument(sketchId <= numFilters, "Sketch id: %s
exceeds number of filters: %s", sketchId,
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/HistogramAggregationFunction.java
b/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/HistogramAggregationFunction.java
index ff1dfa6d81..a2911f5ddc 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/HistogramAggregationFunction.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/HistogramAggregationFunction.java
@@ -67,9 +67,9 @@ public class HistogramAggregationFunction extends
BaseSingleInputAggregationFunc
_upper = _bucketEdges[_bucketEdges.length - 1];
} else {
_isEqualLength = true;
- _lower = Double.parseDouble(arguments.get(1).getLiteral());
- _upper = Double.parseDouble(arguments.get(2).getLiteral());
- int numBins = Integer.parseInt(arguments.get(3).getLiteral());
+ _lower = Double.parseDouble(arguments.get(1).getLiteralString());
+ _upper = Double.parseDouble(arguments.get(2).getLiteralString());
+ int numBins = Integer.parseInt(arguments.get(3).getLiteralString());
Preconditions.checkArgument(_upper > _lower,
"The right most edge must be greater than left most edge, given %s
and %s", _lower, _upper);
Preconditions.checkArgument(numBins > 0, "The number of bins must be
greater than zero, given %s", numBins);
@@ -96,7 +96,12 @@ public class HistogramAggregationFunction extends
BaseSingleInputAggregationFunc
Preconditions.checkArgument(len > 1, "The number of bin edges must be
greater than 1");
double[] ret = new double[len];
for (int i = 0; i < len; i++) {
- ret[i] = Double.parseDouble(arrayStr.get(i).getLiteral());
+ // TODO: Represent infinity as literal instead of identifier
+ if (arrayStr.get(i).getType() == ExpressionContext.Type.IDENTIFIER) {
+ ret[i] = Double.parseDouble(arrayStr.get(i).getIdentifier());
+ } else {
+ ret[i] = Double.parseDouble(arrayStr.get(i).getLiteralString());
+ }
if (i > 0) {
Preconditions.checkState(ret[i] > ret[i - 1], "The bin edges must be
strictly increasing");
}
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/IdSetAggregationFunction.java
b/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/IdSetAggregationFunction.java
index a6e6b34641..b4d5cb18e7 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/IdSetAggregationFunction.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/IdSetAggregationFunction.java
@@ -82,7 +82,7 @@ public class IdSetAggregationFunction extends
BaseSingleInputAggregationFunction
int sizeThresholdInBytes = IdSets.DEFAULT_SIZE_THRESHOLD_IN_BYTES;
int expectedInsertions = IdSets.DEFAULT_EXPECTED_INSERTIONS;
double fpp = IdSets.DEFAULT_FPP;
- String parametersString = parametersExpression.getLiteral();
+ String parametersString = parametersExpression.getLiteralString();
StringUtils.deleteWhitespace(parametersString);
String[] keyValuePairs = StringUtils.split(parametersString,
PARAMETER_DELIMITER);
for (String keyValuePair : keyValuePairs) {
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/ModeAggregationFunction.java
b/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/ModeAggregationFunction.java
index ffc14e4b9d..fb394ad591 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/ModeAggregationFunction.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/ModeAggregationFunction.java
@@ -68,7 +68,7 @@ public class ModeAggregationFunction extends
BaseSingleInputAggregationFunction<
int numArguments = arguments.size();
Preconditions.checkArgument(numArguments <= 2, "Mode expects at most 2
arguments, got: %s", numArguments);
if (numArguments > 1) {
- _multiModeReducerType =
MultiModeReducerType.valueOf(arguments.get(1).getLiteral());
+ _multiModeReducerType =
MultiModeReducerType.valueOf(arguments.get(1).getLiteralString());
} else {
_multiModeReducerType = MultiModeReducerType.MIN;
}
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/PercentileSmartTDigestAggregationFunction.java
b/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/PercentileSmartTDigestAggregationFunction.java
index 6171337160..2697690a60 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/PercentileSmartTDigestAggregationFunction.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/PercentileSmartTDigestAggregationFunction.java
@@ -60,14 +60,14 @@ public class PercentileSmartTDigestAggregationFunction
extends BaseSingleInputAg
public PercentileSmartTDigestAggregationFunction(List<ExpressionContext>
arguments) {
super(arguments.get(0));
try {
- _percentile = Double.parseDouble(arguments.get(1).getLiteral());
+ _percentile = Double.parseDouble(arguments.get(1).getLiteralString());
} catch (Exception e) {
throw new IllegalArgumentException(
"Second argument of PERCENTILE_SMART_TDIGEST aggregation function
must be a double literal (percentile)");
}
Preconditions.checkArgument(_percentile >= 0 && _percentile <= 100,
"Invalid percentile: %s", _percentile);
if (arguments.size() > 2) {
- Parameters parameters = new Parameters(arguments.get(2).getLiteral());
+ Parameters parameters = new
Parameters(arguments.get(2).getLiteralString());
_compression = parameters._compression;
_threshold = parameters._threshold;
} else {
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/SumPrecisionAggregationFunction.java
b/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/SumPrecisionAggregationFunction.java
index a460d30d26..2656389822 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/SumPrecisionAggregationFunction.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/query/aggregation/function/SumPrecisionAggregationFunction.java
@@ -57,9 +57,9 @@ public class SumPrecisionAggregationFunction extends
BaseSingleInputAggregationF
int numArguments = arguments.size();
Preconditions.checkArgument(numArguments <= 3, "SumPrecision expects at
most 3 arguments, got: %s", numArguments);
if (numArguments > 1) {
- _precision = Integer.valueOf(arguments.get(1).getLiteral());
+ _precision = Integer.valueOf(arguments.get(1).getLiteralString());
if (numArguments > 2) {
- _scale = Integer.valueOf(arguments.get(2).getLiteral());
+ _scale = Integer.valueOf(arguments.get(2).getLiteralString());
} else {
_scale = null;
}
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 66461646a7..075882448e 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
@@ -77,6 +77,7 @@ import org.apache.pinot.segment.spi.ImmutableSegment;
import org.apache.pinot.segment.spi.IndexSegment;
import org.apache.pinot.segment.spi.MutableSegment;
import org.apache.pinot.segment.spi.SegmentMetadata;
+import org.apache.pinot.spi.data.FieldSpec;
import org.apache.pinot.spi.env.PinotConfiguration;
import org.apache.pinot.spi.exception.BadQueryRequestException;
import org.apache.pinot.spi.exception.QueryCancelledException;
@@ -611,9 +612,9 @@ public class ServerQueryExecutorV1Impl implements
QueryExecutor {
Preconditions.checkArgument(arguments.size() == 2,
"IN_PARTITIONED_SUBQUERY requires 2 arguments: expression,
subquery");
ExpressionContext subqueryExpression = arguments.get(1);
- Preconditions.checkArgument(subqueryExpression.getType() ==
ExpressionContext.Type.LITERAL,
+ Preconditions.checkState(subqueryExpression.getType() ==
ExpressionContext.Type.LITERAL,
"Second argument of IN_PARTITIONED_SUBQUERY must be a literal
(subquery)");
- QueryContext subquery =
QueryContextConverterUtils.getQueryContext(subqueryExpression.getLiteral());
+ QueryContext subquery =
QueryContextConverterUtils.getQueryContext(subqueryExpression.getLiteralString());
// Subquery should be an ID_SET aggregation only query
//noinspection rawtypes
AggregationFunction[] aggregationFunctions =
subquery.getAggregationFunctions();
@@ -621,7 +622,7 @@ public class ServerQueryExecutorV1Impl implements
QueryExecutor {
&& aggregationFunctions[0].getType() ==
AggregationFunctionType.IDSET
&& subquery.getGroupByExpressions() == null,
"Subquery in IN_PARTITIONED_SUBQUERY should be an ID_SET aggregation
only query, found: %s",
- subqueryExpression.getLiteral());
+ subqueryExpression.toString());
// Execute the subquery
subquery.setEndTimeMs(endTimeMs);
// Make a clone of indexSegments because the method might modify the list
@@ -634,7 +635,7 @@ public class ServerQueryExecutorV1Impl implements
QueryExecutor {
new String(Base64.getEncoder().encode(idSet.getBuffer()).array(),
StandardCharsets.ISO_8859_1);
// Rewrite the expression
function.setFunctionName(TransformFunctionType.INIDSET.name());
- arguments.set(1, ExpressionContext.forLiteral(serializedIdSet));
+ arguments.set(1,
ExpressionContext.forLiteralContext(FieldSpec.DataType.STRING,
serializedIdSet));
} else {
for (ExpressionContext argument : arguments) {
handleSubquery(argument, indexSegments, timerContext, executorService,
endTimeMs);
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/query/reduce/BaseGapfillProcessor.java
b/pinot-core/src/main/java/org/apache/pinot/core/query/reduce/BaseGapfillProcessor.java
index 6059e6ca75..0c37e7f763 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/query/reduce/BaseGapfillProcessor.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/query/reduce/BaseGapfillProcessor.java
@@ -83,16 +83,16 @@ abstract class BaseGapfillProcessor {
List<ExpressionContext> args =
_gapFillSelection.getFunction().getArguments();
- _dateTimeFormatter = new DateTimeFormatSpec(args.get(1).getLiteral());
- _gapfillDateTimeGranularity = new
DateTimeGranularitySpec(args.get(4).getLiteral());
- if (args.get(5).getLiteral() == null) {
+ _dateTimeFormatter = new
DateTimeFormatSpec(args.get(1).getLiteralString());
+ _gapfillDateTimeGranularity = new
DateTimeGranularitySpec(args.get(4).getLiteralString());
+ if (args.get(5).getLiteralString() == null) {
_postGapfillDateTimeGranularity = _gapfillDateTimeGranularity;
} else {
- _postGapfillDateTimeGranularity = new
DateTimeGranularitySpec(args.get(5).getLiteral());
+ _postGapfillDateTimeGranularity = new
DateTimeGranularitySpec(args.get(5).getLiteralString());
}
- String start = args.get(2).getLiteral();
+ String start = args.get(2).getLiteralString();
_startMs = truncate(_dateTimeFormatter.fromFormatToMillis(start));
- String end = args.get(3).getLiteral();
+ String end = args.get(3).getLiteralString();
_endMs = truncate(_dateTimeFormatter.fromFormatToMillis(end));
_gapfillTimeBucketSize = _gapfillDateTimeGranularity.granularityToMillis();
_postGapfillTimeBucketSize =
_postGapfillDateTimeGranularity.granularityToMillis();
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/query/reduce/GapfillFilterHandler.java
b/pinot-core/src/main/java/org/apache/pinot/core/query/reduce/GapfillFilterHandler.java
index 8ec110a0cf..780de965cd 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/query/reduce/GapfillFilterHandler.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/query/reduce/GapfillFilterHandler.java
@@ -67,7 +67,7 @@ public class GapfillFilterHandler implements
ValueExtractorFactory {
expression = GapfillUtils.stripGapfill(expression);
if (expression.getType() == ExpressionContext.Type.LITERAL) {
// Literal
- return new LiteralValueExtractor(expression.getLiteral());
+ return new LiteralValueExtractor(expression.getLiteralString());
}
if (expression.getType() == ExpressionContext.Type.IDENTIFIER) {
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/query/reduce/GapfillProcessor.java
b/pinot-core/src/main/java/org/apache/pinot/core/query/reduce/GapfillProcessor.java
index 3907175b6b..22b1bd9163 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/query/reduce/GapfillProcessor.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/query/reduce/GapfillProcessor.java
@@ -305,10 +305,10 @@ public class GapfillProcessor extends
BaseGapfillProcessor {
if (expressionContext != null && expressionContext.getFunction() != null
&& GapfillUtils
.isFill(expressionContext)) {
List<ExpressionContext> args =
expressionContext.getFunction().getArguments();
- if (args.get(1).getLiteral() == null) {
+ if (args.get(1).getLiteralString() == null) {
throw new UnsupportedOperationException("Wrong Sql.");
}
- GapfillUtils.FillType fillType =
GapfillUtils.FillType.valueOf(args.get(1).getLiteral());
+ GapfillUtils.FillType fillType =
GapfillUtils.FillType.valueOf(args.get(1).getLiteralString());
if (fillType == GapfillUtils.FillType.FILL_DEFAULT_VALUE) {
// TODO: may fill the default value from sql in the future.
return GapfillUtils.getDefaultValue(dataType);
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/query/reduce/PostAggregationHandler.java
b/pinot-core/src/main/java/org/apache/pinot/core/query/reduce/PostAggregationHandler.java
index 4c4bcaf03c..516ce76f9d 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/query/reduce/PostAggregationHandler.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/query/reduce/PostAggregationHandler.java
@@ -108,7 +108,7 @@ public class PostAggregationHandler implements
ValueExtractorFactory {
public ValueExtractor getValueExtractor(ExpressionContext expression) {
if (expression.getType() == ExpressionContext.Type.LITERAL) {
// Literal
- return new LiteralValueExtractor(expression.getLiteral());
+ return new LiteralValueExtractor(expression.getLiteralString());
}
if (_numGroupByExpressions > 0) {
Integer groupByExpressionIndex =
_groupByExpressionIndexMap.get(expression);
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/query/reduce/SumAvgGapfillProcessor.java
b/pinot-core/src/main/java/org/apache/pinot/core/query/reduce/SumAvgGapfillProcessor.java
index e0a560563f..835a2c753c 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/query/reduce/SumAvgGapfillProcessor.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/query/reduce/SumAvgGapfillProcessor.java
@@ -66,7 +66,7 @@ class SumAvgGapfillProcessor extends BaseGapfillProcessor {
}
ExpressionContext arg =
expressionContext.getFunction().getArguments().get(0);
for (int j = 0; j < dataSchema.getColumnNames().length; j++) {
- if (arg.getLiteral().equalsIgnoreCase(dataSchema.getColumnName(j))) {
+ if
(arg.getIdentifier().equalsIgnoreCase(dataSchema.getColumnName(j))) {
_sumArgIndexes[i] = j;
break;
}
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/util/GapfillUtils.java
b/pinot-core/src/main/java/org/apache/pinot/core/util/GapfillUtils.java
index aca1a435b3..bd39d34720 100644
--- a/pinot-core/src/main/java/org/apache/pinot/core/util/GapfillUtils.java
+++ b/pinot-core/src/main/java/org/apache/pinot/core/util/GapfillUtils.java
@@ -172,7 +172,8 @@ public class GapfillUtils {
"The second argument of Gapfill should be TimeFormatter.");
Preconditions.checkArgument(args.get(2).getLiteral() != null,
"The third argument of Gapfill should be start time.");
- Preconditions.checkArgument(args.get(3).getLiteral() != null, "The fourth
argument of Gapfill should be end time.");
+ Preconditions.checkArgument(args.get(3).getLiteral() != null,
+ "The fourth argument of Gapfill should be end time.");
Preconditions.checkArgument(args.get(4).getLiteral() != null,
"The fifth argument of Gapfill should be time bucket size.");
diff --git
a/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/LiteralTransformFunctionTest.java
b/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/LiteralTransformFunctionTest.java
index 754ab5b59a..5fccb613ec 100644
---
a/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/LiteralTransformFunctionTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/core/operator/transform/function/LiteralTransformFunctionTest.java
@@ -18,6 +18,7 @@
*/
package org.apache.pinot.core.operator.transform.function;
+import org.apache.pinot.common.request.context.LiteralContext;
import org.apache.pinot.spi.data.FieldSpec.DataType;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -33,8 +34,12 @@ public class LiteralTransformFunctionTest {
Assert.assertEquals(LiteralTransformFunction.inferLiteralDataType("1.2"),
DataType.FLOAT);
Assert.assertEquals(LiteralTransformFunction.inferLiteralDataType("41241241.2412"),
DataType.DOUBLE);
Assert.assertEquals(LiteralTransformFunction.inferLiteralDataType("1.7976931348623159e+308"),
DataType.BIG_DECIMAL);
- Assert.assertEquals(LiteralTransformFunction.inferLiteralDataType("true"),
DataType.BOOLEAN);
-
Assert.assertEquals(LiteralTransformFunction.inferLiteralDataType("false"),
DataType.BOOLEAN);
Assert.assertEquals(LiteralTransformFunction.inferLiteralDataType("2020-02-02
20:20:20.20"), DataType.TIMESTAMP);
+ LiteralTransformFunction trueBoolean = new LiteralTransformFunction(new
LiteralContext(DataType.BOOLEAN, true));
+ Assert.assertEquals(trueBoolean.getResultMetadata().getDataType(),
DataType.BOOLEAN);
+ Assert.assertEquals(trueBoolean.getLiteral(), "true");
+ LiteralTransformFunction falseBoolean = new LiteralTransformFunction(new
LiteralContext(DataType.BOOLEAN, false));
+ Assert.assertEquals(falseBoolean.getResultMetadata().getDataType(),
DataType.BOOLEAN);
+ Assert.assertEquals(falseBoolean.getLiteral(), "false");
}
}
diff --git
a/pinot-core/src/test/java/org/apache/pinot/core/plan/maker/QueryOverrideWithHintsTest.java
b/pinot-core/src/test/java/org/apache/pinot/core/plan/maker/QueryOverrideWithHintsTest.java
index e725dfa4ff..35ae0d685d 100644
---
a/pinot-core/src/test/java/org/apache/pinot/core/plan/maker/QueryOverrideWithHintsTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/core/plan/maker/QueryOverrideWithHintsTest.java
@@ -41,6 +41,7 @@ import org.apache.pinot.segment.spi.SegmentMetadata;
import org.apache.pinot.segment.spi.datasource.DataSource;
import
org.apache.pinot.segment.spi.index.mutable.ThreadSafeMutableRoaringBitmap;
import org.apache.pinot.segment.spi.index.startree.StarTreeV2;
+import org.apache.pinot.spi.data.FieldSpec;
import org.apache.pinot.spi.data.readers.GenericRow;
import org.apache.pinot.sql.parsers.CalciteSqlParser;
import org.testng.annotations.Test;
@@ -115,29 +116,32 @@ public class QueryOverrideWithHintsTest {
expressionContext2 = ExpressionContext.forIdentifier("");
assertNotEquals(expressionContext1, expressionContext2);
assertNotEquals(expressionContext1.hashCode(),
expressionContext2.hashCode());
-
- expressionContext1 = ExpressionContext.forLiteral("abc");
- expressionContext2 = ExpressionContext.forLiteral("abc");
+ expressionContext1 =
ExpressionContext.forLiteralContext(FieldSpec.DataType.STRING, "abc");
+ expressionContext2 =
ExpressionContext.forLiteralContext(FieldSpec.DataType.STRING, "abc");
assertEquals(expressionContext1, expressionContext2);
assertEquals(expressionContext1.hashCode(), expressionContext2.hashCode());
- expressionContext2 = ExpressionContext.forLiteral("abcd");
+ expressionContext2 =
ExpressionContext.forLiteralContext(FieldSpec.DataType.STRING, "abcd");
assertNotEquals(expressionContext1, expressionContext2);
assertNotEquals(expressionContext1.hashCode(),
expressionContext2.hashCode());
- expressionContext2 = ExpressionContext.forLiteral("");
+ expressionContext2 =
ExpressionContext.forLiteralContext(FieldSpec.DataType.STRING, "");
assertNotEquals(expressionContext1, expressionContext2);
assertNotEquals(expressionContext1.hashCode(),
expressionContext2.hashCode());
expressionContext1 = ExpressionContext.forFunction(new
FunctionContext(FunctionContext.Type.TRANSFORM, "func1",
- ImmutableList.of(ExpressionContext.forIdentifier("abc"),
ExpressionContext.forLiteral("abc"))));
+ ImmutableList.of(ExpressionContext.forIdentifier("abc"),
+ ExpressionContext.forLiteralContext(FieldSpec.DataType.STRING,
"abc"))));
expressionContext2 = ExpressionContext.forFunction(new
FunctionContext(FunctionContext.Type.TRANSFORM, "func1",
- ImmutableList.of(ExpressionContext.forIdentifier("abc"),
ExpressionContext.forLiteral("abc"))));
+ ImmutableList.of(ExpressionContext.forIdentifier("abc"),
+ ExpressionContext.forLiteralContext(FieldSpec.DataType.STRING,
"abc"))));
assertEquals(expressionContext1, expressionContext2);
assertEquals(expressionContext1.hashCode(), expressionContext2.hashCode());
expressionContext1 = ExpressionContext.forFunction(new
FunctionContext(FunctionContext.Type.TRANSFORM, "datetrunc",
- ImmutableList.of(ExpressionContext.forLiteral("DAY"),
ExpressionContext.forLiteral("event_time_ts"))));
+
ImmutableList.of(ExpressionContext.forLiteralContext(FieldSpec.DataType.STRING,
"DAY"),
+ ExpressionContext.forLiteralContext(FieldSpec.DataType.STRING,
"event_time_ts"))));
expressionContext2 = ExpressionContext.forFunction(new
FunctionContext(FunctionContext.Type.TRANSFORM, "datetrunc",
- ImmutableList.of(ExpressionContext.forLiteral("DAY"),
ExpressionContext.forLiteral("event_time_ts"))));
+
ImmutableList.of(ExpressionContext.forLiteralContext(FieldSpec.DataType.STRING,
"DAY"),
+ ExpressionContext.forLiteralContext(FieldSpec.DataType.STRING,
"event_time_ts"))));
assertEquals(expressionContext1, expressionContext2);
assertEquals(expressionContext1.hashCode(), expressionContext2.hashCode());
}
@@ -146,11 +150,13 @@ public class QueryOverrideWithHintsTest {
public void testOverrideFilterWithExpressionOverrideHints() {
ExpressionContext dateTruncFunctionExpr = ExpressionContext.forFunction(
new FunctionContext(FunctionContext.Type.TRANSFORM, "dateTrunc", new
ArrayList<>(new ArrayList<>(
- ImmutableList.of(ExpressionContext.forLiteral("MONTH"),
ExpressionContext.forIdentifier("ts"))))));
+
ImmutableList.of(ExpressionContext.forLiteralContext(FieldSpec.DataType.STRING,
"MONTH"),
+ ExpressionContext.forIdentifier("ts"))))));
ExpressionContext timestampIndexColumn =
ExpressionContext.forIdentifier("$ts$MONTH");
ExpressionContext equalsExpression = ExpressionContext.forFunction(
- new FunctionContext(FunctionContext.Type.TRANSFORM, "EQUALS",
- new ArrayList<>(ImmutableList.of(dateTruncFunctionExpr,
ExpressionContext.forLiteral("1000")))));
+ new FunctionContext(FunctionContext.Type.TRANSFORM, "EQUALS", new
ArrayList<>(
+ ImmutableList.of(dateTruncFunctionExpr,
+ ExpressionContext.forLiteralContext(FieldSpec.DataType.INT,
1000)))));
FilterContext filter = RequestContextUtils.getFilter(equalsExpression);
Map<ExpressionContext, ExpressionContext> hints =
ImmutableMap.of(dateTruncFunctionExpr, timestampIndexColumn);
InstancePlanMakerImplV2.overrideWithExpressionHints(filter, _indexSegment,
hints);
@@ -170,35 +176,41 @@ public class QueryOverrideWithHintsTest {
public void testOverrideWithExpressionOverrideHints() {
ExpressionContext dateTruncFunctionExpr = ExpressionContext.forFunction(
new FunctionContext(FunctionContext.Type.TRANSFORM, "dateTrunc", new
ArrayList<>(
- ImmutableList.of(ExpressionContext.forLiteral("MONTH"),
ExpressionContext.forIdentifier("ts")))));
+
ImmutableList.of(ExpressionContext.forLiteralContext(FieldSpec.DataType.STRING,
"MONTH"),
+ ExpressionContext.forIdentifier("ts")))));
ExpressionContext timestampIndexColumn =
ExpressionContext.forIdentifier("$ts$MONTH");
ExpressionContext equalsExpression = ExpressionContext.forFunction(
- new FunctionContext(FunctionContext.Type.TRANSFORM, "EQUALS",
- new ArrayList<>(ImmutableList.of(dateTruncFunctionExpr,
ExpressionContext.forLiteral("1000")))));
+ new FunctionContext(FunctionContext.Type.TRANSFORM, "EQUALS", new
ArrayList<>(
+ ImmutableList.of(dateTruncFunctionExpr,
+ ExpressionContext.forLiteralContext(FieldSpec.DataType.INT,
1000)))));
Map<ExpressionContext, ExpressionContext> hints =
ImmutableMap.of(dateTruncFunctionExpr, timestampIndexColumn);
ExpressionContext newEqualsExpression =
InstancePlanMakerImplV2.overrideWithExpressionHints(equalsExpression,
_indexSegment, hints);
assertEquals(newEqualsExpression.getFunction().getFunctionName(),
"equals");
assertEquals(newEqualsExpression.getFunction().getArguments().get(0),
timestampIndexColumn);
- assertEquals(newEqualsExpression.getFunction().getArguments().get(1),
ExpressionContext.forLiteral("1000"));
+ assertEquals(newEqualsExpression.getFunction().getArguments().get(1),
+ ExpressionContext.forLiteralContext(FieldSpec.DataType.INT, 1000));
}
@Test
public void testNotOverrideWithExpressionOverrideHints() {
ExpressionContext dateTruncFunctionExpr = ExpressionContext.forFunction(
new FunctionContext(FunctionContext.Type.TRANSFORM, "dateTrunc", new
ArrayList<>(
- ImmutableList.of(ExpressionContext.forLiteral("DAY"),
ExpressionContext.forIdentifier("ts")))));
+
ImmutableList.of(ExpressionContext.forLiteralContext(FieldSpec.DataType.STRING,
"DAY"),
+ ExpressionContext.forIdentifier("ts")))));
ExpressionContext timestampIndexColumn =
ExpressionContext.forIdentifier("$ts$DAY");
ExpressionContext equalsExpression = ExpressionContext.forFunction(
- new FunctionContext(FunctionContext.Type.TRANSFORM, "EQUALS",
- new ArrayList<>(ImmutableList.of(dateTruncFunctionExpr,
ExpressionContext.forLiteral("1000")))));
+ new FunctionContext(FunctionContext.Type.TRANSFORM, "EQUALS", new
ArrayList<>(
+ ImmutableList.of(dateTruncFunctionExpr,
+ ExpressionContext.forLiteralContext(FieldSpec.DataType.INT,
1000)))));
Map<ExpressionContext, ExpressionContext> hints =
ImmutableMap.of(dateTruncFunctionExpr, timestampIndexColumn);
ExpressionContext newEqualsExpression =
InstancePlanMakerImplV2.overrideWithExpressionHints(equalsExpression,
_indexSegment, hints);
assertEquals(newEqualsExpression.getFunction().getFunctionName(),
"equals");
// No override as the physical column is not in the index segment.
assertEquals(newEqualsExpression.getFunction().getArguments().get(0),
dateTruncFunctionExpr);
- assertEquals(newEqualsExpression.getFunction().getArguments().get(1),
ExpressionContext.forLiteral("1000"));
+ assertEquals(newEqualsExpression.getFunction().getArguments().get(1),
+ ExpressionContext.forLiteralContext(FieldSpec.DataType.INT, 1000));
}
@Test
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 e4367f8a6b..018bb275f4 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
@@ -37,6 +37,7 @@ import
org.apache.pinot.core.query.aggregation.function.CountAggregationFunction
import org.apache.pinot.core.query.aggregation.function.MinAggregationFunction;
import org.apache.pinot.core.query.aggregation.function.SumAggregationFunction;
import org.apache.pinot.core.query.request.context.QueryContext;
+import org.apache.pinot.spi.data.FieldSpec;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
@@ -177,11 +178,13 @@ public class BrokerRequestToQueryContextConverterTest {
new FunctionContext(FunctionContext.Type.TRANSFORM, "add",
Arrays.asList(ExpressionContext.forIdentifier("foo"),
ExpressionContext.forFunction(
new FunctionContext(FunctionContext.Type.TRANSFORM, "add",
- Arrays.asList(ExpressionContext.forIdentifier("bar"),
ExpressionContext.forLiteral("123"))))))));
+ Arrays.asList(ExpressionContext.forIdentifier("bar"),
+
ExpressionContext.forLiteralContext(FieldSpec.DataType.LONG,
Long.valueOf(123)))))))));
assertEquals(selectExpressions.get(0).toString(),
"add(foo,add(bar,'123'))");
assertEquals(selectExpressions.get(1), ExpressionContext.forFunction(
new FunctionContext(FunctionContext.Type.TRANSFORM, "sub",
- Arrays.asList(ExpressionContext.forLiteral("456"),
ExpressionContext.forIdentifier("foobar")))));
+
Arrays.asList(ExpressionContext.forLiteralContext(FieldSpec.DataType.STRING,
"456"),
+ ExpressionContext.forIdentifier("foobar")))));
assertEquals(selectExpressions.get(1).toString(), "sub('456',foobar)");
assertEquals(getAliasCount(queryContext.getAliasList()), 0);
assertNull(queryContext.getFilter());
@@ -191,7 +194,8 @@ public class BrokerRequestToQueryContextConverterTest {
assertEquals(orderByExpressions.size(), 1);
assertEquals(orderByExpressions.get(0), new
OrderByExpressionContext(ExpressionContext.forFunction(
new FunctionContext(FunctionContext.Type.TRANSFORM, "sub",
- Arrays.asList(ExpressionContext.forLiteral("456"),
ExpressionContext.forIdentifier("foobar")))), true));
+
Arrays.asList(ExpressionContext.forLiteralContext(FieldSpec.DataType.LONG,
Long.valueOf(456)),
+ ExpressionContext.forIdentifier("foobar")))), true));
assertEquals(orderByExpressions.get(0).toString(), "sub('456',foobar)
ASC");
assertNull(queryContext.getHavingFilter());
assertEquals(queryContext.getLimit(), 20);
@@ -202,6 +206,17 @@ public class BrokerRequestToQueryContextConverterTest {
assertFalse(QueryContextUtils.isDistinctQuery(queryContext));
}
+ // Boolean literal parsing
+ {
+ String query = "SELECT true = true FROM testTable;";
+ QueryContext queryContext =
QueryContextConverterUtils.getQueryContext(query);
+ assertEquals(queryContext.getTableName(), "testTable");
+ List<ExpressionContext> selectExpressions =
queryContext.getSelectExpressions();
+ assertEquals(selectExpressions.size(), 1);
+ assertEquals(selectExpressions.get(0),
ExpressionContext.forLiteralContext(FieldSpec.DataType.BOOLEAN, true));
+ assertEquals(selectExpressions.get(0).toString(), "'true'");
+ }
+
// Aggregation group-by with transform, order-by
{
String query =
@@ -485,10 +500,12 @@ public class BrokerRequestToQueryContextConverterTest {
assertEquals(function.getFunctionName(), "distinctcountthetasketch");
List<ExpressionContext> arguments = function.getArguments();
assertEquals(arguments.get(0), ExpressionContext.forIdentifier("foo"));
- assertEquals(arguments.get(1),
ExpressionContext.forLiteral("nominalEntries=1000"));
- assertEquals(arguments.get(2), ExpressionContext.forLiteral("bar='a'"));
- assertEquals(arguments.get(3), ExpressionContext.forLiteral("bar='b'"));
- assertEquals(arguments.get(4),
ExpressionContext.forLiteral("SET_INTERSECT($1, $2)"));
+ assertEquals(arguments.get(1),
+ ExpressionContext.forLiteralContext(FieldSpec.DataType.STRING,
"nominalEntries=1000"));
+ assertEquals(arguments.get(2),
ExpressionContext.forLiteralContext(FieldSpec.DataType.STRING, "bar='a'"));
+ assertEquals(arguments.get(3),
ExpressionContext.forLiteralContext(FieldSpec.DataType.STRING, "bar='b'"));
+ assertEquals(arguments.get(4),
+ ExpressionContext.forLiteralContext(FieldSpec.DataType.STRING,
"SET_INTERSECT($1, $2)"));
assertEquals(queryContext.getColumns(), new
HashSet<>(Arrays.asList("foo", "bar")));
assertFalse(QueryContextUtils.isSelectionQuery(queryContext));
assertTrue(QueryContextUtils.isAggregationQuery(queryContext));
diff --git
a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/OfflineClusterIntegrationTest.java
b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/OfflineClusterIntegrationTest.java
index 6df759103a..1fdd46d5b5 100644
---
a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/OfflineClusterIntegrationTest.java
+++
b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/OfflineClusterIntegrationTest.java
@@ -2792,4 +2792,37 @@ public class OfflineClusterIntegrationTest extends
BaseClusterIntegrationTestSet
assertEquals(jobStatus.get("metadata").get("jobType").asText(),
"RELOAD_ALL_SEGMENTS");
return jobStatus.get("totalSegmentCount").asInt() ==
jobStatus.get("successCount").asInt();
}
+
+ @Test
+ public void testBooleanLiteralsFunc()
+ throws Exception {
+ // Test boolean equal true case.
+ String sqlQuery = "SELECT (true = true) = true FROM mytable where true =
true";
+ JsonNode response = postQuery(sqlQuery, _brokerBaseApiUrl);
+ JsonNode rows = response.get("resultTable").get("rows");
+ assertTrue(response.get("exceptions").isEmpty());
+ assertEquals(rows.size(), 1);
+ assertTrue(rows.get(0).get(0).asBoolean());
+ // Test boolean equal false case.
+ sqlQuery = "SELECT (true = true) = false FROM mytable";
+ response = postQuery(sqlQuery, _brokerBaseApiUrl);
+ rows = response.get("resultTable").get("rows");
+ assertTrue(response.get("exceptions").isEmpty());
+ assertEquals(rows.size(), 1);
+ assertFalse(rows.get(0).get(0).asBoolean());
+ // Test boolean not equal true case.
+ sqlQuery = "SELECT true != false FROM mytable";
+ response = postQuery(sqlQuery, _brokerBaseApiUrl);
+ rows = response.get("resultTable").get("rows");
+ assertTrue(response.get("exceptions").isEmpty());
+ assertEquals(rows.size(), 1);
+ assertTrue(rows.get(0).get(0).asBoolean());
+ // Test boolean not equal false case.
+ sqlQuery = "SELECT true != true FROM mytable";
+ response = postQuery(sqlQuery, _brokerBaseApiUrl);
+ rows = response.get("resultTable").get("rows");
+ assertTrue(response.get("exceptions").isEmpty());
+ assertEquals(rows.size(), 1);
+ assertFalse(rows.get(0).get(0).asBoolean());
+ }
}
diff --git
a/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/AggregateOperator.java
b/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/AggregateOperator.java
index b304ed5903..6747b07ef4 100644
---
a/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/AggregateOperator.java
+++
b/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/AggregateOperator.java
@@ -204,7 +204,7 @@ public class AggregateOperator extends
BaseOperator<TransferableBlock> {
ExpressionContext.forIdentifier(String.valueOf(aggregationFunctionInputRef)));
// COUNT(*) is rewritten to SUM(1)
case "COUNT":
- return new SumAggregationFunction(ExpressionContext.forLiteral("1"));
+ return new
SumAggregationFunction(ExpressionContext.forLiteralContext(FieldSpec.DataType.INT,
1));
default:
throw new IllegalStateException(
"Unexpected value: " + ((RexExpression.FunctionCall)
aggCall).getFunctionName());
diff --git
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/function/InbuiltFunctionEvaluator.java
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/function/InbuiltFunctionEvaluator.java
index 18e1ee5031..2399fdefe7 100644
---
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/function/InbuiltFunctionEvaluator.java
+++
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/function/InbuiltFunctionEvaluator.java
@@ -54,7 +54,8 @@ public class InbuiltFunctionEvaluator implements
FunctionEvaluator {
private ExecutableNode planExecution(ExpressionContext expression) {
switch (expression.getType()) {
case LITERAL:
- return new ConstantExecutionNode(expression.getLiteral());
+ // TODO: pass literal with type into ConstantExecutionNode.
+ return new ConstantExecutionNode(expression.getLiteralString());
case IDENTIFIER:
String columnName = expression.getIdentifier();
ColumnExecutionNode columnExecutionNode = new
ColumnExecutionNode(columnName, _arguments.size());
diff --git
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/indexsegment/mutable/MutableSegmentImpl.java
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/indexsegment/mutable/MutableSegmentImpl.java
index cc6e552358..a91076b093 100644
---
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/indexsegment/mutable/MutableSegmentImpl.java
+++
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/indexsegment/mutable/MutableSegmentImpl.java
@@ -1408,7 +1408,7 @@ public class MutableSegmentImpl implements MutableSegment
{
AggregationFunctionType.getAggregationFunctionType(functionContext.getFunctionName());
columnNameToAggregator.put(config.getColumnName(),
- Pair.of(argument.getLiteral(),
ValueAggregatorFactory.getValueAggregator(functionType)));
+ Pair.of(argument.getIdentifier(),
ValueAggregatorFactory.getValueAggregator(functionType)));
}
return columnNameToAggregator;
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]