This is an automated email from the ASF dual-hosted git repository.
siddteotia pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-pinot.git
The following commit(s) were added to refs/heads/master by this push:
new e0b2be8 Normalize LHS and RHS numerical types for >, >=, <, and <=
operators. (#6927)
e0b2be8 is described below
commit e0b2be8c989aa35d966808989d62fb5def00e088
Author: Amrish Lal <[email protected]>
AuthorDate: Thu May 27 22:58:03 2021 -0700
Normalize LHS and RHS numerical types for >, >=, <, and <= operators.
(#6927)
* Normalize LHS and RHS numerical types for >, >=, <, and <= operators.
* Rebuild.
* Cleanup.
* codereview changes.
---
.../optimizer/filter/NumericalFilterOptimizer.java | 294 ++++++++++++---
.../filter/NumericalFilterOptimizerTest.java | 405 +++++++++++----------
2 files changed, 443 insertions(+), 256 deletions(-)
diff --git
a/pinot-core/src/main/java/org/apache/pinot/core/query/optimizer/filter/NumericalFilterOptimizer.java
b/pinot-core/src/main/java/org/apache/pinot/core/query/optimizer/filter/NumericalFilterOptimizer.java
index 88ff24c..f580897 100644
---
a/pinot-core/src/main/java/org/apache/pinot/core/query/optimizer/filter/NumericalFilterOptimizer.java
+++
b/pinot-core/src/main/java/org/apache/pinot/core/query/optimizer/filter/NumericalFilterOptimizer.java
@@ -33,22 +33,25 @@ import org.apache.pinot.spi.data.Schema;
/**
- * Numerical expressions of form "column = literal" or "column != literal" can
compare a column of one datatype
- * (say INT) with a literal of different datatype (say DOUBLE). These
expressions can not be evaluated on the Server.
- * Hence, we rewrite such expressions into an equivalent expression whose LHS
and RHS are of the same datatype.
+ * Numerical expressions of form "column <operator> literal", where operator
can be '=', '!=', '>', '>=', '<', or '<=',
+ * can compare a column of one datatype (say INT) with a literal of different
datatype (say DOUBLE). These expressions
+ * can not be evaluated on the Server. Hence, we rewrite such expressions into
an equivalent expression whose LHS and
+ * RHS are of the same datatype.
*
* Simple predicate examples:
* 1) WHERE "intColumn = 5.0" gets rewritten to "WHERE intColumn = 5"
* 2) WHERE "intColumn != 5.0" gets rewritten to "WHERE intColumn != 5"
* 3) WHERE "intColumn = 5.5" gets rewritten to "WHERE false" because INT
values can not match 5.5.
- * 4) WHERE "intColumn = 3000000000 gets rewritten to "WHERE false" because
INT values can not match 3000000000.
- * 5) WHERE "intColumn != 3000000000 gets rewritten to "WHERE true" becuase
INT values always not equal to 3000000000.
+ * 4) WHERE "intColumn = 3000000000" gets rewritten to "WHERE false" because
INT values can not match 3000000000.
+ * 5) WHERE "intColumn != 3000000000" gets rewritten to "WHERE true" because
INT values always not equal to 3000000000.
+ * 6) WHERE "intColumn < 5.1" gets rewritten to "WHERE intColumn <= 5"
+ * 7) WHERE "intColumn > -3E9" gets rewritten to "WHERE true" because int
values are always greater than -3E9.
*
* Compound predicate examples:
- * 6) WHERE "intColumn1 = 5.5 AND intColumn2 = intColumn3"
+ * 8) WHERE "intColumn1 = 5.5 AND intColumn2 = intColumn3"
* rewrite to "WHERE false AND intColumn2 = intColumn3"
* rewrite to "WHERE intColumn2 = intColumn3"
- * 7) WHERE "intColumn1 != 5.5 OR intColumn2 = 5000000000" (5000000000 is out
of bounds for integer column)
+ * 9) WHERE "intColumn1 != 5.5 OR intColumn2 = 5000000000" (5000000000 is out
of bounds for integer column)
* rewrite to "WHERE true OR false"
* rewrite to "WHERE true"
* rewrite to query without any WHERE clause.
@@ -56,6 +59,8 @@ import org.apache.pinot.spi.data.Schema;
* When entire predicate gets rewritten to false (Example 3 above), the query
will not return any data. Hence, it is
* better for the Broker itself to return an empty response rather than
sending the query to servers for further
* evaluation.
+ *
+ * TODO: Add support for BETWEEN, IN, and NOT IN operators.
*/
public class NumericalFilterOptimizer implements FilterOptimizer {
@@ -80,22 +85,29 @@ public class NumericalFilterOptimizer implements
FilterOptimizer {
List<Expression> operands = function.getOperands();
String operator = function.getOperator();
if (operator.equals(FilterKind.AND.name()) ||
operator.equals(FilterKind.OR.name())) {
- // One of the operands may be an EQUALS or NOT_EQUALS function so
recursively traverse the expression tree to see
- // if we find an EQUALS or NOT_EQUALS function to rewrite.
+ // Recursively traverse the expression tree to find an operator node
that can be rewritten.
operands.forEach(operand -> optimize(operand, schema));
// We have rewritten the child operands, so rewrite the parent if needed.
return optimizeCurrent(expression);
- } else if (operator.equals(FilterKind.EQUALS.name()) ||
operator.equals(FilterKind.NOT_EQUALS.name())) {
+ } else {
// Verify that LHS is a numeric column and RHS is a numeric literal
before rewriting.
Expression lhs = operands.get(0);
Expression rhs = operands.get(1);
if (isNumericColumn(lhs, schema) && isNumericLiteral(rhs)) {
- // Rewrite the expression.
- return rewrite(expression, lhs, rhs, schema);
+ FilterKind kind = FilterKind.valueOf(operator);
+ switch (kind) {
+ case EQUALS:
+ case NOT_EQUALS:
+ return rewriteEqualsExpression(expression, kind, lhs, rhs, schema);
+ case GREATER_THAN:
+ case GREATER_THAN_OR_EQUAL:
+ case LESS_THAN:
+ case LESS_THAN_OR_EQUAL:
+ return rewriteRangeExpression(expression, kind, lhs, rhs, schema);
+ }
}
}
-
return expression;
}
@@ -139,52 +151,13 @@ public class NumericalFilterOptimizer implements
FilterOptimizer {
return expression;
}
- private boolean isNumericColumn(Expression expression, Schema schema) {
- if (expression.getType() != ExpressionType.IDENTIFIER) {
- // Expression can not be a column.
- return false;
- }
-
- String column = expression.getIdentifier().getName();
- FieldSpec fieldSpec = schema.getFieldSpecFor(column);
- if (fieldSpec == null || !fieldSpec.isSingleValueField()) {
- // Expression can not be a column name.
- return false;
- }
-
- return schema.getFieldSpecFor(column).getDataType().isNumeric();
- }
-
- private boolean isNumericLiteral(Expression expression) {
- if (expression.getType() == ExpressionType.LITERAL) {
- Literal._Fields type = expression.getLiteral().getSetField();
- switch (type) {
- case SHORT_VALUE:
- case INT_VALUE:
- case LONG_VALUE:
- case DOUBLE_VALUE:
- return true;
- }
- }
- return false;
- }
-
- /** Change the expression value to boolean literal with given value. */
- private static Expression setExpressionToBoolean(Expression expression,
boolean value) {
- expression.unsetFunctionCall();
- expression.setType(ExpressionType.LITERAL);
- expression.setLiteral(Literal.boolValue(value));
-
- return expression;
- }
-
/**
* Rewrite expressions of form "column = literal" or "column != literal" to
ensure that RHS literal is the same
* datatype as LHS column.
*/
- private Expression rewrite(Expression equals, Expression lhs, Expression
rhs, Schema schema) {
+ private static Expression rewriteEqualsExpression(Expression equals,
FilterKind kind, Expression lhs, Expression rhs, Schema schema) {
// Get expression operator
- boolean result =
equals.getFunctionCall().getOperator().equals(FilterKind.NOT_EQUALS.name());
+ boolean result = kind == FilterKind.NOT_EQUALS;
// Get column data type.
FieldSpec.DataType dataType =
schema.getFieldSpecFor(lhs.getIdentifier().getName()).getDataType();
@@ -234,7 +207,7 @@ public class NumericalFilterOptimizer implements
FilterOptimizer {
}
break;
}
- case DOUBLE_VALUE:
+ case DOUBLE_VALUE: {
double actual = rhs.getLiteral().getDoubleValue();
switch (dataType) {
case INT: {
@@ -271,7 +244,218 @@ public class NumericalFilterOptimizer implements
FilterOptimizer {
break;
}
}
+ }
}
return equals;
}
+
+ /**
+ * Rewrite expressions of form "column > literal", "column >= literal",
"column < literal", and "column <= literal"
+ * to ensure that RHS literal is the same datatype as LHS column.
+ */
+ private static Expression rewriteRangeExpression(Expression range,
FilterKind kind, Expression lhs, Expression rhs, Schema schema) {
+ // Get column data type.
+ FieldSpec.DataType dataType =
schema.getFieldSpecFor(lhs.getIdentifier().getName()).getDataType();
+
+ switch (rhs.getLiteral().getSetField()) {
+ case SHORT_VALUE:
+ case INT_VALUE:
+ // No rewrites needed since SHORT and INT conversion to numeric column
types (INT, LONG, FLOAT, and DOUBLE) is
+ // lossless and will be implicitly handled on the server side.
+ break;
+ case LONG_VALUE: {
+ long actual = rhs.getLiteral().getLongValue();
+ switch (dataType) {
+ case INT: {
+ int converted = (int) actual;
+ int comparison = Long.compare(actual, converted);
+ if (comparison > 0) {
+ // Literal value is greater than the bounds of INT. > and >=
expressions will always be false because an
+ // INT column can never have a value greater than
Integer.MAX_VALUE. < and <= expressions will always be
+ // true, because an INT column will always have values greater
than or equal to Integer.MIN_VALUE and less
+ // than or equal to Integer.MAX_VALUE.
+ setExpressionToBoolean(range, kind == FilterKind.LESS_THAN ||
kind == FilterKind.LESS_THAN_OR_EQUAL);
+ } else if (comparison < 0) {
+ // Literal value is less than the bounds of INT. > and >=
expressions will always be true because an
+ // INT column will always have a value greater than or equal to
Integer.MIN_VALUE. < and <= expressions
+ // will always be false, because an INT column will never have
values less than Integer.MIN_VALUE.
+ setExpressionToBoolean(range, kind == FilterKind.GREATER_THAN ||
kind == FilterKind.GREATER_THAN_OR_EQUAL);
+ } else {
+ // Long literal value falls within the bounds of INT column,
server will successfully convert the literal
+ // value when needed.
+ }
+ break;
+ }
+ case FLOAT: {
+ // Since we are converting a long value to float, float value will
never be out of bounds (i.e -Infinity
+ // or +Infinity).
+ float converted = (float) actual;
+ int comparison =
BigDecimal.valueOf(actual).compareTo(BigDecimal.valueOf(converted));
+
+ // Rewrite range operator
+ rewriteRangeOperator(range, kind, comparison);
+
+ // Rewrite range literal
+ rhs.getLiteral().setDoubleValue(converted);
+ break;
+ }
+ case DOUBLE: {
+ // long to double conversion is always within bounds of double
datatype, but the conversion can be lossy.
+ // Example:
+ // Original long value : 9223372036854775807 (Long.MAX_VALUE)
+ // Converted double value: 9.223372036854776E18
+ // This conversion is lossy because the last four digits of the
long value (5807) had to be rounded off
+ // to 6. After conversion we lost all information about the
existence of last four digits. Converting the
+ // double value back to long will not result in original long
value.
+ double converted = (double) actual;
+ int comparison =
BigDecimal.valueOf(actual).compareTo(BigDecimal.valueOf(converted));
+
+ // Rewrite range operator
+ rewriteRangeOperator(range, kind, comparison);
+
+ // Rewrite range literal
+ rhs.getLiteral().setDoubleValue(converted);
+ break;
+ }
+ }
+ break;
+ }
+ case DOUBLE_VALUE: {
+ double actual = rhs.getLiteral().getDoubleValue();
+ switch (dataType) {
+ case INT: {
+ int converted = (int) actual;
+ int comparison = Double.compare(actual, converted);
+ if (comparison > 0 && converted == Integer.MAX_VALUE) {
+ // Literal value is greater than the bounds of INT.
+ setExpressionToBoolean(range, kind == FilterKind.LESS_THAN ||
kind == FilterKind.LESS_THAN_OR_EQUAL);
+ } else if (comparison < 0 && converted == Integer.MIN_VALUE) {
+ // Literal value is less than the bounds of INT.
+ setExpressionToBoolean(range, kind == FilterKind.GREATER_THAN ||
kind == FilterKind.GREATER_THAN_OR_EQUAL);
+ } else {
+ // Literal value falls within the bounds of INT.
+ rewriteRangeOperator(range, kind, comparison);
+
+ // Rewrite range literal
+ rhs.getLiteral().setLongValue(converted);
+ }
+ break;
+ }
+ case LONG: {
+ long converted = (long) actual;
+ int comparison =
BigDecimal.valueOf(actual).compareTo(BigDecimal.valueOf(converted));
+
+ if (comparison > 0 && converted == Long.MAX_VALUE) {
+ // Literal value is greater than the bounds of LONG.
+ setExpressionToBoolean(range, kind == FilterKind.LESS_THAN ||
kind == FilterKind.LESS_THAN_OR_EQUAL);
+ } else if (comparison < 0 && converted == Long.MIN_VALUE) {
+ // Literal value is less than the bounds of LONG.
+ setExpressionToBoolean(range, kind == FilterKind.GREATER_THAN ||
kind == FilterKind.GREATER_THAN_OR_EQUAL);
+ } else {
+ // Rewrite range operator
+ rewriteRangeOperator(range, kind, comparison);
+
+ // Rewrite range literal
+ rhs.getLiteral().setLongValue(converted);
+ }
+ break;
+ }
+ case FLOAT: {
+ float converted = (float) actual;
+ if (converted == Float.POSITIVE_INFINITY) {
+ // Literal value is greater than the bounds of FLOAT
+ setExpressionToBoolean(range, kind == FilterKind.LESS_THAN ||
kind == FilterKind.LESS_THAN_OR_EQUAL);
+ } else if (converted == Float.NEGATIVE_INFINITY) {
+ // Literal value is less than the bounds of LONG.
+ setExpressionToBoolean(range, kind == FilterKind.GREATER_THAN ||
kind == FilterKind.GREATER_THAN_OR_EQUAL);
+ } else {
+ int comparison = Double.compare(actual, converted);
+ // Rewrite range operator
+ rewriteRangeOperator(range, kind, comparison);
+
+ // Rewrite range literal
+ rhs.getLiteral().setDoubleValue(converted);
+ }
+ break;
+ }
+ }
+ }
+ }
+ return range;
+ }
+
+ /**
+ * Helper function to rewrite range operator of a range expression.
+ * @param range Range expression.
+ * @param kind The kind of range filter being used in the range expression.
+ * @param comparison -1 (literal < converted value), 0 (literal == converted
value), 1 (literal > converted value).
+ */
+ private static void rewriteRangeOperator(Expression range, FilterKind kind,
int comparison) {
+ if (comparison > 0) {
+ // Literal value is greater than the converted value, so rewrite:
+ // "column > literal" to "column > converted"
+ // "column >= literal" to "column >= converted"
+ // "column < literal" to "column <= converted"
+ // "column <= literal" to "column < converted"
+ if (kind == FilterKind.GREATER_THAN || kind ==
FilterKind.GREATER_THAN_OR_EQUAL) {
+ range.getFunctionCall().setOperator(FilterKind.GREATER_THAN.name());
+ } else if (kind == FilterKind.LESS_THAN || kind ==
FilterKind.LESS_THAN_OR_EQUAL) {
+
range.getFunctionCall().setOperator(FilterKind.LESS_THAN_OR_EQUAL.name());
+ }
+ } else if (comparison < 0) {
+ // Literal value is less than the converted value, so rewrite:
+ // "column > literal" to "column >= converted"
+ // "column >= literal" to "column >= converted"
+ // "column < literal" to "column < converted"
+ // "column <= literal" to "column < converted"
+ if (kind == FilterKind.GREATER_THAN || kind ==
FilterKind.GREATER_THAN_OR_EQUAL) {
+
range.getFunctionCall().setOperator(FilterKind.GREATER_THAN_OR_EQUAL.name());
+ } else if (kind == FilterKind.LESS_THAN || kind ==
FilterKind.LESS_THAN_OR_EQUAL) {
+ range.getFunctionCall().setOperator(FilterKind.LESS_THAN.name());
+ }
+ } else {
+ // No need to rewrite range expression since conversion of literal value
was lossless.
+ }
+ }
+
+ /** @return true if expression is a column of numeric type */
+ private static boolean isNumericColumn(Expression expression, Schema schema)
{
+ if (expression.getType() != ExpressionType.IDENTIFIER) {
+ // Expression can not be a column.
+ return false;
+ }
+
+ String column = expression.getIdentifier().getName();
+ FieldSpec fieldSpec = schema.getFieldSpecFor(column);
+ if (fieldSpec == null || !fieldSpec.isSingleValueField()) {
+ // Expression can not be a column name.
+ return false;
+ }
+
+ return schema.getFieldSpecFor(column).getDataType().isNumeric();
+ }
+
+ /** @return true if expression is a numeric literal; otherwise, false. */
+ private static boolean isNumericLiteral(Expression expression) {
+ if (expression.getType() == ExpressionType.LITERAL) {
+ Literal._Fields type = expression.getLiteral().getSetField();
+ switch (type) {
+ case SHORT_VALUE:
+ case INT_VALUE:
+ case LONG_VALUE:
+ case DOUBLE_VALUE:
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /** Change the expression value to boolean literal with given value. */
+ private static Expression setExpressionToBoolean(Expression expression,
boolean value) {
+ expression.unsetFunctionCall();
+ expression.setType(ExpressionType.LITERAL);
+ expression.setLiteral(Literal.boolValue(value));
+
+ return expression;
+ }
}
diff --git
a/pinot-core/src/test/java/org/apache/pinot/core/query/optimizer/filter/NumericalFilterOptimizerTest.java
b/pinot-core/src/test/java/org/apache/pinot/core/query/optimizer/filter/NumericalFilterOptimizerTest.java
index 55af556..5e631fb 100644
---
a/pinot-core/src/test/java/org/apache/pinot/core/query/optimizer/filter/NumericalFilterOptimizerTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/core/query/optimizer/filter/NumericalFilterOptimizerTest.java
@@ -41,274 +41,277 @@ public class NumericalFilterOptimizerTest {
.addMultiValueDimension("mvIntColumn",
FieldSpec.DataType.INT).build();
@Test
- public void testEqualsIntColumnWithValidDecimalValue() {
- BrokerRequest sqlBrokerRequest =
- SQL_COMPILER.compileToBrokerRequest("SELECT * FROM testTable WHERE
intColumn = 5.0");
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
-
- // "intColumn = 5.0" should have been rewritten to "intColumn = 5" since
5.0 converts to integer value without any
- // loss of information.
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
+ public void testEqualsRewrites() {
+ // Test int column equals valid decimal value. "intColumn = 5.0" should
have been rewritten to "intColumn = 5"
+ // since 5.0 converts to integer value without any loss of information.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn =
5.0"),
"Expression(type:FUNCTION, functionCall:Function(operator:EQUALS,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:intColumn)),
Expression(type:LITERAL, literal:<Literal longValue:5>)]))");
- }
-
- @Test
- public void testEqualsIntColumnWithInvalidDecimalValue() {
- BrokerRequest sqlBrokerRequest =
- SQL_COMPILER.compileToBrokerRequest("SELECT * FROM testTable WHERE
intColumn = 5.5");
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
+ // Test int column equals invalid decimal value.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn =
5.5"),
"Expression(type:LITERAL, literal:<Literal boolValue:false>)");
- }
- @Test
- public void testNotEqualsIntColumnWithValidDecimalValue() {
- BrokerRequest sqlBrokerRequest =
- SQL_COMPILER.compileToBrokerRequest("SELECT * FROM testTable WHERE
intColumn != 5.0");
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
-
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
+ // Test int column not equals valid decimal value.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn !=
5.0"),
"Expression(type:FUNCTION, functionCall:Function(operator:NOT_EQUALS,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:intColumn)),
Expression(type:LITERAL, literal:<Literal longValue:5>)]))");
- }
- @Test
- public void testNotEqualsIntColumnWithInvalidDecimalValue() {
- BrokerRequest sqlBrokerRequest =
- SQL_COMPILER.compileToBrokerRequest("SELECT * FROM testTable WHERE
intColumn != 5.5");
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
+ // Test int column not equals invalid decimal value.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn !=
5.5"),
+ "Expression(type:LITERAL, literal:<Literal boolValue:true>)");
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
+ // Test int column equals out of domain value.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn =
5000000000"),
+ "Expression(type:LITERAL, literal:<Literal boolValue:false>)");
+
+ // Test int column not equals out of domain value.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn !=
5000000000"),
"Expression(type:LITERAL, literal:<Literal boolValue:true>)");
- }
- @Test
- public void testEqualsIntColumnWithOutOfDomainValue() {
- BrokerRequest sqlBrokerRequest =
- SQL_COMPILER.compileToBrokerRequest("SELECT * FROM testTable WHERE
intColumn = 5000000000");
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
+ // Test long column equals valid decimal value. "longColumn = 5.0" should
be rewritten to "longColumn = 5" since 5.0
+ // converts to long value without any loss of information.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE longColumn =
5.0"),
+ "Expression(type:FUNCTION, functionCall:Function(operator:EQUALS,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:longColumn)),
Expression(type:LITERAL, literal:<Literal longValue:5>)]))");
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
+ // Test long column equals invalid decimal value. "longColumn = 5.5"
should have been rewritten to "false" literal
+ // since an LONG column can never have a decimal value.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE longColumn =
5.5"),
"Expression(type:LITERAL, literal:<Literal boolValue:false>)");
- }
- @Test
- public void testNotEqualsIntColumnWithOutOfDomainValue() {
- BrokerRequest sqlBrokerRequest =
- SQL_COMPILER.compileToBrokerRequest("SELECT * FROM testTable WHERE
intColumn != 5000000000");
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
+ // Test long column with valid decimal value. "longColumn = 5.5" should
have been rewritten to "false" literal since
+ // LONG column can never have a decimal value.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE longColumn !=
5.0"),
+ "Expression(type:FUNCTION, functionCall:Function(operator:NOT_EQUALS,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:longColumn)),
Expression(type:LITERAL, literal:<Literal longValue:5>)]))");
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
+ // Test long column not equals invalid decimal value.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE longColumn !=
5.5"),
"Expression(type:LITERAL, literal:<Literal boolValue:true>)");
- }
- @Test
- public void testEqualsLongColumnWithValidDecimalValue() {
- BrokerRequest sqlBrokerRequest =
- SQL_COMPILER.compileToBrokerRequest("SELECT * FROM testTable WHERE
longColumn = 5.0");
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
+ // Test float column equals valid long value.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE floatColumn =
5"),
+ "Expression(type:FUNCTION, functionCall:Function(operator:EQUALS,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:floatColumn)),
Expression(type:LITERAL, literal:<Literal doubleValue:5.0>)]))");
- // "intColumn = 5.0" should have been rewritten to "intColumn = 5" since
5.0 converts to integer value without any
- // loss of information.
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
- "Expression(type:FUNCTION, functionCall:Function(operator:EQUALS,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:longColumn)),
Expression(type:LITERAL, literal:<Literal longValue:5>)]))");
- }
+ // Test float column equals invalid long value.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE floatColumn = "
+ String.valueOf(Long.MAX_VALUE)),
+ "Expression(type:LITERAL, literal:<Literal boolValue:false>)");
- @Test
- public void testEqualsLongColumnWithInvalidDecimalValue() {
- BrokerRequest sqlBrokerRequest =
- SQL_COMPILER.compileToBrokerRequest("SELECT * FROM testTable WHERE
longColumn = 5.5");
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
+ // Test float column not equals valid long value
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE floatColumn !=
" + String.valueOf(Long.MAX_VALUE)),
+ "Expression(type:LITERAL, literal:<Literal boolValue:true>)");
+
+ // Test float column not equals valid long value
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE floatColumn !=
5"),
+ "Expression(type:FUNCTION, functionCall:Function(operator:NOT_EQUALS,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:floatColumn)),
Expression(type:LITERAL, literal:<Literal doubleValue:5.0>)]))");
+
+ // test double column equals valid long value.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE doubleColumn =
5"),
+ "Expression(type:FUNCTION, functionCall:Function(operator:EQUALS,
operands:[Expression(type:IDENTIFIER,
identifier:Identifier(name:doubleColumn)), Expression(type:LITERAL,
literal:<Literal doubleValue:5.0>)]))");
- // "intColumn = 5.5" should have been rewritten to "false" literal since
an INT column can never have a decimal
- // value.
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
+ // Test double column equals invalid long value.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE doubleColumn =
" + String.valueOf(Long.MAX_VALUE)),
"Expression(type:LITERAL, literal:<Literal boolValue:false>)");
- }
- @Test
- public void testNotEqualsLongColumnWithValidDecimalValue() {
- BrokerRequest sqlBrokerRequest =
- SQL_COMPILER.compileToBrokerRequest("SELECT * FROM testTable WHERE
longColumn != 5.0");
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
+ // Test double column not equals valid long value
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE doubleColumn !=
" + String.valueOf(Long.MAX_VALUE)),
+ "Expression(type:LITERAL, literal:<Literal boolValue:true>)");
- // "intColumn = 5.5" should have been rewritten to "false" literal since
an INT column can never have a decimal
- // value.
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
- "Expression(type:FUNCTION, functionCall:Function(operator:NOT_EQUALS,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:longColumn)),
Expression(type:LITERAL, literal:<Literal longValue:5>)]))");
+ // Test double column not equals invalid long value.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE doubleColumn !=
5"),
+ "Expression(type:FUNCTION, functionCall:Function(operator:NOT_EQUALS,
operands:[Expression(type:IDENTIFIER,
identifier:Identifier(name:doubleColumn)), Expression(type:LITERAL,
literal:<Literal doubleValue:5.0>)]))");
}
@Test
- public void testNotEqualsLongColumnWithInvalidDecimalValue() {
- BrokerRequest sqlBrokerRequest =
- SQL_COMPILER.compileToBrokerRequest("SELECT * FROM testTable WHERE
longColumn != 5.5");
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
+ public void testRangeRewrites() {
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
+ // Test INT column with DOUBLE value greater than Integer.MAX_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn >
3000000000.0"),
+ "Expression(type:LITERAL, literal:<Literal boolValue:false>)");
+
+ // Test INT column with DOUBLE value greater than Integer.MAX_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn <
3000000000.0"),
"Expression(type:LITERAL, literal:<Literal boolValue:true>)");
- }
- @Test
- public void testEqualsFloatColumnWithValidLongValue() {
- BrokerRequest sqlBrokerRequest =
- SQL_COMPILER.compileToBrokerRequest("SELECT * FROM testTable WHERE
floatColumn = 5");
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
+ // Test INT column with DOUBLE value greater than Integer.MIN_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn >
-3000000000.0"),
+ "Expression(type:LITERAL, literal:<Literal boolValue:true>)");
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
- "Expression(type:FUNCTION, functionCall:Function(operator:EQUALS,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:floatColumn)),
Expression(type:LITERAL, literal:<Literal doubleValue:5.0>)]))");
- }
+ // Test INT column with LONG value less than Integer.MIN_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn <
-3000000000"),
+ "Expression(type:LITERAL, literal:<Literal boolValue:false>)");
- @Test
- public void testEqualsFloatColumnWithInvalidLongValue() {
- BrokerRequest sqlBrokerRequest = SQL_COMPILER
- .compileToBrokerRequest("SELECT * FROM testTable WHERE floatColumn = "
+ String.valueOf(Long.MAX_VALUE));
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
+ // Test INT column with LONG value greater than Integer.MAX_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn >
3000000000"),
+ "Expression(type:LITERAL, literal:<Literal boolValue:false>)");
+
+ // Test INT column with LONG value greater than Integer.MAX_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn <
3000000000"),
+ "Expression(type:LITERAL, literal:<Literal boolValue:true>)");
+
+ // Test INT column with LONG value greater than Integer.MIN_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn >
-3000000000"),
+ "Expression(type:LITERAL, literal:<Literal boolValue:true>)");
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
+ // Test INT column with LONG value less than Integer.MIN_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn <
-3000000000"),
"Expression(type:LITERAL, literal:<Literal boolValue:false>)");
- }
- @Test
- public void testNotEqualsFloatColumnWithValidLongValue() {
- BrokerRequest sqlBrokerRequest = SQL_COMPILER
- .compileToBrokerRequest("SELECT * FROM testTable WHERE floatColumn !=
" + String.valueOf(Long.MAX_VALUE));
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
+ // Test INT column with DOUBLE value that falls within INT bounds.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn <
-2100000000.5"),
+ "Expression(type:FUNCTION, functionCall:Function(operator:LESS_THAN,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:intColumn)),
Expression(type:LITERAL, literal:<Literal longValue:-2100000000>)]))");
+
+ // Test INT column with DOUBLE value that falls within INT bounds.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn <
2100000000.5"),
+ "Expression(type:FUNCTION,
functionCall:Function(operator:LESS_THAN_OR_EQUAL,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:intColumn)),
Expression(type:LITERAL, literal:<Literal longValue:2100000000>)]))");
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
+ // Test FLOAT column greater than Double.MAX_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE floatColumn > "
+ Double.MAX_VALUE),
+ "Expression(type:LITERAL, literal:<Literal boolValue:false>)");
+
+ // Test FLOAT column less than Double.MAX_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE floatColumn < "
+ Double.MAX_VALUE),
"Expression(type:LITERAL, literal:<Literal boolValue:true>)");
- }
- @Test
- public void testNotEqualsFloatColumnWithInvalidLongValue() {
- BrokerRequest sqlBrokerRequest =
- SQL_COMPILER.compileToBrokerRequest("SELECT * FROM testTable WHERE
floatColumn != 5");
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
+ // Test FLOAT column greater than -Double.MAX_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE floatColumn > "
+ -Double.MAX_VALUE),
+ "Expression(type:LITERAL, literal:<Literal boolValue:true>)");
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
- "Expression(type:FUNCTION, functionCall:Function(operator:NOT_EQUALS,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:floatColumn)),
Expression(type:LITERAL, literal:<Literal doubleValue:5.0>)]))");
- }
+ // Test FLOAT column less than -Double.MAX_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE floatColumn < "
+ -Double.MAX_VALUE),
+ "Expression(type:LITERAL, literal:<Literal boolValue:false>)");
- @Test
- public void testEqualsDoubleColumnWithValidLongValue() {
- BrokerRequest sqlBrokerRequest =
- SQL_COMPILER.compileToBrokerRequest("SELECT * FROM testTable WHERE
doubleColumn = 5");
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
+ // Test FLOAT column greater than Long.MAX_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE floatColumn > "
+ Long.MAX_VALUE),
+ "Expression(type:FUNCTION,
functionCall:Function(operator:GREATER_THAN_OR_EQUAL,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:floatColumn)),
Expression(type:LITERAL, literal:<Literal
doubleValue:9.223372036854776E18>)]))");
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
- "Expression(type:FUNCTION, functionCall:Function(operator:EQUALS,
operands:[Expression(type:IDENTIFIER,
identifier:Identifier(name:doubleColumn)), Expression(type:LITERAL,
literal:<Literal doubleValue:5.0>)]))");
- }
+ // Test FLOAT column less than Long.MIN_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE floatColumn < "
+ Long.MIN_VALUE),
+ "Expression(type:FUNCTION,
functionCall:Function(operator:LESS_THAN_OR_EQUAL,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:floatColumn)),
Expression(type:LITERAL, literal:<Literal
doubleValue:-9.223372036854776E18>)]))");
- @Test
- public void testEqualsDoubleColumnWithInvalidLongValue() {
- BrokerRequest sqlBrokerRequest = SQL_COMPILER
- .compileToBrokerRequest("SELECT * FROM testTable WHERE doubleColumn =
" + String.valueOf(Long.MAX_VALUE));
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
+ // Test FLOAT column greater than Long.MIN_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE floatColumn > "
+ Long.MIN_VALUE),
+ "Expression(type:FUNCTION,
functionCall:Function(operator:GREATER_THAN,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:floatColumn)),
Expression(type:LITERAL, literal:<Literal
doubleValue:-9.223372036854776E18>)]))");
+
+ // Test FLOAT column with DOUBLE value that is within bounds of FLOAT.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE floatColumn >
-2100000000.5"),
+ "Expression(type:FUNCTION,
functionCall:Function(operator:GREATER_THAN_OR_EQUAL,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:floatColumn)),
Expression(type:LITERAL, literal:<Literal doubleValue:-2.1E9>)]))");
+
+ // Test FLOAT column with DOUBLE value that is within bounds of FLOAT.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE floatColumn <
-2100000000.5"),
+ "Expression(type:FUNCTION, functionCall:Function(operator:LESS_THAN,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:floatColumn)),
Expression(type:LITERAL, literal:<Literal doubleValue:-2.1E9>)]))");
+
+ // Test FLOAT column with DOUBLE value that is within bounds of FLOAT.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE floatColumn <=
2100000000.5"),
+ "Expression(type:FUNCTION,
functionCall:Function(operator:LESS_THAN_OR_EQUAL,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:floatColumn)),
Expression(type:LITERAL, literal:<Literal doubleValue:2.1E9>)]))");
+
+ // Test FLOAT column with DOUBLE value that is within bounds of FLOAT.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE floatColumn >=
2100000000.5"),
+ "Expression(type:FUNCTION,
functionCall:Function(operator:GREATER_THAN,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:floatColumn)),
Expression(type:LITERAL, literal:<Literal doubleValue:2.1E9>)]))");
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
+ // Test LONG column with DOUBLE value greater than Long.MAX_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE longColumn >
999999999999999999999999999999.9999"),
"Expression(type:LITERAL, literal:<Literal boolValue:false>)");
- }
- @Test
- public void testNotEqualsDoubleColumnWithValidLongValue() {
- BrokerRequest sqlBrokerRequest = SQL_COMPILER
- .compileToBrokerRequest("SELECT * FROM testTable WHERE doubleColumn !=
" + String.valueOf(Long.MAX_VALUE));
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
+ // Test LONG column with DOUBLE value greater than Long.MAX_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE longColumn <
999999999999999999999999999999.9999"),
+ "Expression(type:LITERAL, literal:<Literal boolValue:true>)");
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
+ // Test LONG column with DOUBLE value greater than Long.MIN_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE longColumn >
-999999999999999999999999999999.9999"),
"Expression(type:LITERAL, literal:<Literal boolValue:true>)");
- }
- @Test
- public void testNotEqualsDoubleColumnWithInvalidLongValue() {
- BrokerRequest sqlBrokerRequest =
- SQL_COMPILER.compileToBrokerRequest("SELECT * FROM testTable WHERE
doubleColumn != 5");
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
+ // Test LONG column with DOUBLE value that falls within LONG bounds.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE longColumn <
-2100000000.5"),
+ "Expression(type:FUNCTION, functionCall:Function(operator:LESS_THAN,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:longColumn)),
Expression(type:LITERAL, literal:<Literal longValue:-2100000000>)]))");
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
- "Expression(type:FUNCTION, functionCall:Function(operator:NOT_EQUALS,
operands:[Expression(type:IDENTIFIER,
identifier:Identifier(name:doubleColumn)), Expression(type:LITERAL,
literal:<Literal doubleValue:5.0>)]))");
- }
+ // Test LONG column with DOUBLE value that falls within LONG bounds.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE longColumn >
-2100000000.5"),
+ "Expression(type:FUNCTION,
functionCall:Function(operator:GREATER_THAN_OR_EQUAL,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:longColumn)),
Expression(type:LITERAL, literal:<Literal longValue:-2100000000>)]))");
+
+ // Test LONG column with DOUBLE value that falls within LONG bounds.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE longColumn <
2100000000.5"),
+ "Expression(type:FUNCTION,
functionCall:Function(operator:LESS_THAN_OR_EQUAL,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:longColumn)),
Expression(type:LITERAL, literal:<Literal longValue:2100000000>)]))");
+
+ // Test LONG column with DOUBLE value that falls within LONG bounds.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE longColumn >
2100000000.5"),
+ "Expression(type:FUNCTION,
functionCall:Function(operator:GREATER_THAN,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:longColumn)),
Expression(type:LITERAL, literal:<Literal longValue:2100000000>)]))");
+
+ // Test DOUBLE column greater than Long.MAX_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE doubleColumn >
" + Long.MAX_VALUE),
+ "Expression(type:FUNCTION,
functionCall:Function(operator:GREATER_THAN_OR_EQUAL,
operands:[Expression(type:IDENTIFIER,
identifier:Identifier(name:doubleColumn)), Expression(type:LITERAL,
literal:<Literal doubleValue:9.223372036854776E18>)]))");
+
+ // Test DOUBLE column less than Long.MIN_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE doubleColumn <
" + Long.MIN_VALUE),
+ "Expression(type:FUNCTION,
functionCall:Function(operator:LESS_THAN_OR_EQUAL,
operands:[Expression(type:IDENTIFIER,
identifier:Identifier(name:doubleColumn)), Expression(type:LITERAL,
literal:<Literal doubleValue:-9.223372036854776E18>)]))");
+
+ // Test DOUBLE column greater than Long.MIN_VALUE.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE doubleColumn >
" + Long.MIN_VALUE),
+ "Expression(type:FUNCTION,
functionCall:Function(operator:GREATER_THAN,
operands:[Expression(type:IDENTIFIER,
identifier:Identifier(name:doubleColumn)), Expression(type:LITERAL,
literal:<Literal doubleValue:-9.223372036854776E18>)]))");
- @Test
- public void testAndWithAllTrueOperands() {
- BrokerRequest sqlBrokerRequest =
- SQL_COMPILER.compileToBrokerRequest("SELECT * FROM testTable WHERE
intColumn != 5.5 AND longColumn != 6.4");
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
- "Expression(type:LITERAL, literal:<Literal boolValue:true>)");
}
@Test
- public void testAndWithAllFalseOperands() {
- BrokerRequest sqlBrokerRequest =
- SQL_COMPILER.compileToBrokerRequest("SELECT * FROM testTable WHERE
intColumn = 5.5 AND longColumn = 6.4");
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
+ public void temp() {
+
+ // Test LONG column with DOUBLE value that falls within LONG bounds.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE longColumn <
-2100000000.5"),
+ "Expression(type:FUNCTION, functionCall:Function(operator:LESS_THAN,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:longColumn)),
Expression(type:LITERAL, literal:<Literal longValue:-2100000000>)]))");
+
+ // Test LONG column with DOUBLE value that falls within LONG bounds.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE longColumn >
-2100000000.5"),
+ "Expression(type:FUNCTION,
functionCall:Function(operator:GREATER_THAN_OR_EQUAL,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:longColumn)),
Expression(type:LITERAL, literal:<Literal longValue:-2100000000>)]))");
+
+ // Test LONG column with DOUBLE value that falls within LONG bounds.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE longColumn <
2100000000.5"),
+ "Expression(type:FUNCTION,
functionCall:Function(operator:LESS_THAN_OR_EQUAL,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:longColumn)),
Expression(type:LITERAL, literal:<Literal longValue:2100000000>)]))");
+
+ // Test LONG column with DOUBLE value that falls within LONG bounds.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE longColumn >
2100000000.5"),
+ "Expression(type:FUNCTION,
functionCall:Function(operator:GREATER_THAN,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:longColumn)),
Expression(type:LITERAL, literal:<Literal longValue:2100000000>)]))");
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
- "Expression(type:LITERAL, literal:<Literal boolValue:false>)");
}
@Test
- public void testAndWithOneFalseOperands() {
- BrokerRequest sqlBrokerRequest =
- SQL_COMPILER.compileToBrokerRequest("SELECT * FROM testTable WHERE
intColumn = 5.5 AND longColumn != 6.4");
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
+ public void testAndRewrites() {
+ // Test and with all true operands
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn !=
5.5 AND longColumn != 6.4"),
+ "Expression(type:LITERAL, literal:<Literal boolValue:true>)");
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
+ // Test and with all false operands
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn = 5.5
AND longColumn = 6.4"),
"Expression(type:LITERAL, literal:<Literal boolValue:false>)");
- }
- @Test
- public void testOrWithAllTrueOperands() {
- BrokerRequest sqlBrokerRequest =
- SQL_COMPILER.compileToBrokerRequest("SELECT * FROM testTable WHERE
intColumn != 5.5 OR longColumn != 6.4");
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
+ // Test and with one false operand
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn = 5.5
AND longColumn != 6.4"),
+ "Expression(type:LITERAL, literal:<Literal boolValue:false>)");
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
+ // Test or with all true operands
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn !=
5.5 OR longColumn != 6.4"),
"Expression(type:LITERAL, literal:<Literal boolValue:true>)");
+
+ // Test int column with exclusive valid double value.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn > 5.0
AND intColumn < 10.0"),
+ "Expression(type:FUNCTION, functionCall:Function(operator:RANGE,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:intColumn)),
Expression(type:LITERAL, literal:<Literal stringValue:(5\u000010)>)]))");
+
+ // Test int column with inclusive valid double value.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn >=
5.0 AND intColumn <= 10.0"),
+ "Expression(type:FUNCTION, functionCall:Function(operator:RANGE,
operands:[Expression(type:IDENTIFIER, identifier:Identifier(name:intColumn)),
Expression(type:LITERAL, literal:<Literal stringValue:[5\u000010]>)]))");
}
@Test
- public void testOrWithAllFalseOperands() {
- BrokerRequest sqlBrokerRequest =
- SQL_COMPILER.compileToBrokerRequest("SELECT * FROM testTable WHERE
intColumn = 5.5 OR longColumn = 6.4");
- PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
- OPTIMIZER.optimize(pinotQuery, SCHEMA);
-
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
+ public void testOrRewrites() {
+ // Test or with all false operands
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn = 5.5
OR longColumn = 6.4"),
"Expression(type:LITERAL, literal:<Literal boolValue:false>)");
+
+ // Test or with one false operand.
+ Assert.assertEquals(rewrite("SELECT * FROM testTable WHERE intColumn !=
5.5 OR longColumn = 6.4"),
+ "Expression(type:LITERAL, literal:<Literal boolValue:true>)");
}
- @Test
- public void testOrWithOneFalseOperands() {
- BrokerRequest sqlBrokerRequest =
- SQL_COMPILER.compileToBrokerRequest("SELECT * FROM testTable WHERE
intColumn != 5.5 OR longColumn = 6.4");
+ private static String rewrite(String query) {
+ BrokerRequest sqlBrokerRequest =
SQL_COMPILER.compileToBrokerRequest(query);
PinotQuery pinotQuery = sqlBrokerRequest.getPinotQuery();
OPTIMIZER.optimize(pinotQuery, SCHEMA);
-
- Assert.assertEquals(pinotQuery.getFilterExpression().toString(),
- "Expression(type:LITERAL, literal:<Literal boolValue:true>)");
+ return pinotQuery.getFilterExpression().toString();
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]