ashishjayamohan commented on code in PR #14385:
URL: https://github.com/apache/pinot/pull/14385#discussion_r1970474848
##########
pinot-core/src/main/java/org/apache/pinot/core/query/optimizer/filter/TimePredicateFilterOptimizer.java:
##########
@@ -411,6 +427,94 @@ && isStringLiteral(dateTimeConvertOperands.get(3)),
}
}
+ private void optimizeDateTrunc(Function filterFunction, FilterKind
filterKind) {
+ List<Expression> filterOperands = filterFunction.getOperands();
+ List<Expression> dateTruncOperands =
filterOperands.get(0).getFunctionCall().getOperands();
+
+ if (dateTruncOperands.get(1).isSetLiteral()) {
+ return;
+ }
+
+ Long lowerMillis = null;
+ Long upperMillis = null;
+ boolean lowerInclusive = true;
+ boolean upperInclusive = true;
+ List<Expression> operands = new ArrayList<>(dateTruncOperands);
+ String unit = operands.get(0).getLiteral().getStringValue();
+ String inputTimeUnit = (operands.size() >= 3) ?
operands.get(2).getLiteral().getStringValue()
+ : TimeUnit.MILLISECONDS.name();
+ if (operands.size() >= 4) {
+ if (!operands.get(3).getLiteral().getStringValue().equals("UTC")) {
+ // Leave query unoptimized if working with non-UTC time zones
+ return;
+ }
+ }
+ ISOChronology chronology = ISOChronology.getInstanceUTC();
+ String outputTimeUnit = (operands.size() == 5) ?
operands.get(4).getLiteral().getStringValue()
+ : TimeUnit.MILLISECONDS.name();
+ switch (filterKind) {
+ case EQUALS:
+ operands.set(1, getExpression(getLongValue(filterOperands.get(1)), new
DateTimeFormatSpec("TIMESTAMP")));
+ upperMillis = dateTruncCeil(operands);
+ lowerMillis = dateTruncFloor(operands);
+ if (lowerMillis != DateTimeUtils.getTimestampField(chronology,
unit).roundFloor(lowerMillis)) {
+ lowerMillis = Long.MAX_VALUE;
+ upperMillis = Long.MIN_VALUE;
+ String rangeString = new Range(lowerMillis, lowerInclusive,
upperMillis, upperInclusive).getRangeString();
+ rewriteToRange(filterFunction, dateTruncOperands.get(1),
rangeString);
+ return;
+ }
+ break;
+ case GREATER_THAN:
+ operands.set(1, getExpression(getLongValue(filterOperands.get(1)), new
DateTimeFormatSpec("TIMESTAMP")));
+ lowerMillis = dateTruncCeil(operands);
+ lowerInclusive = false;
+ upperMillis = Long.MAX_VALUE;
+ break;
+ case GREATER_THAN_OR_EQUAL:
+ operands.set(1, getExpression(getLongValue(filterOperands.get(1)), new
DateTimeFormatSpec("TIMESTAMP")));
+ lowerMillis = dateTruncFloor(operands);
+ upperMillis = Long.MAX_VALUE;
+ if (lowerMillis != DateTimeUtils.getTimestampField(chronology,
unit).roundFloor(lowerMillis)) {
Review Comment:
I've left some comments on each check that should explain why these checks
is necessary. That being said, for "less than or equal" filters, we don't need
to check if because the ceiling of the inverse function (inclusive) will always
truncate to a value that is less than or equal to the literal, regardless of
whether the literal is aligned to the unit's stride or not.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]