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: commits-unsubscr...@pinot.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org
For additional commands, e-mail: commits-h...@pinot.apache.org

Reply via email to