This is an automated email from the ASF dual-hosted git repository.

jackie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new 4bafac8439 Add minor optimization for FIRST_VALUE / LAST_VALUE with 
IGNORE NULLS and unbounded ROWS window frame (#14324)
4bafac8439 is described below

commit 4bafac8439e006750308ad8031c373791c594b1c
Author: Yash Mayya <yash.ma...@gmail.com>
AuthorDate: Wed Oct 30 00:16:13 2024 +0530

    Add minor optimization for FIRST_VALUE / LAST_VALUE with IGNORE NULLS and 
unbounded ROWS window frame (#14324)
---
 .../window/value/FirstValueWindowFunction.java     | 35 ++++++++++++++--------
 .../window/value/LastValueWindowFunction.java      | 29 +++++++++++-------
 .../operator/window/value/ValueWindowFunction.java |  7 -----
 3 files changed, 42 insertions(+), 29 deletions(-)

diff --git 
a/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/FirstValueWindowFunction.java
 
b/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/FirstValueWindowFunction.java
index a1f84be32e..7baebe8b41 100644
--- 
a/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/FirstValueWindowFunction.java
+++ 
b/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/FirstValueWindowFunction.java
@@ -58,11 +58,12 @@ public class FirstValueWindowFunction extends 
ValueWindowFunction {
   }
 
   private List<Object> processRowsWindow(List<Object[]> rows) {
+    int numRows = rows.size();
+
     if (_windowFrame.isUnboundedPreceding() && _windowFrame.getUpperBound() >= 
0) {
-      return fillAllWithValue(rows, extractValueFromRow(rows.get(0)));
+      return Collections.nCopies(numRows, extractValueFromRow(rows.get(0)));
     }
 
-    int numRows = rows.size();
     List<Object> result = new ArrayList<>(numRows);
 
     // lowerBound is guaranteed to be less than or equal to upperBound here 
(but both can be -ve / +ve)
@@ -92,6 +93,10 @@ public class FirstValueWindowFunction extends 
ValueWindowFunction {
   }
 
   private List<Object> processRowsWindowIgnoreNulls(List<Object[]> rows) {
+    if (_windowFrame.isUnboundedPreceding() && 
_windowFrame.isUnboundedFollowing()) {
+      return processUnboundedWindowIgnoreNulls(rows);
+    }
+
     int numRows = rows.size();
     int lowerBound = _windowFrame.getLowerBound();
     int upperBound = Math.min(_windowFrame.getUpperBound(), numRows - 1);
@@ -143,15 +148,16 @@ public class FirstValueWindowFunction extends 
ValueWindowFunction {
   }
 
   private List<Object> processRangeWindow(List<Object[]> rows) {
+    int numRows = rows.size();
+
     if (_windowFrame.isUnboundedPreceding()) {
-      return fillAllWithValue(rows, extractValueFromRow(rows.get(0)));
+      return Collections.nCopies(numRows, extractValueFromRow(rows.get(0)));
     }
 
     // The lower bound has to be CURRENT ROW since we don't support RANGE 
windows with offset value
     Preconditions.checkState(_windowFrame.isLowerBoundCurrentRow(),
         "RANGE window frame with offset PRECEDING / FOLLOWING is not 
supported");
 
-    int numRows = rows.size();
     List<Object> result = new ArrayList<>(numRows);
 
     // The window frame here is either RANGE BETWEEN CURRENT ROW AND UNBOUNDED 
FOLLOWING or RANGE BETWEEN CURRENT ROW
@@ -178,14 +184,7 @@ public class FirstValueWindowFunction extends 
ValueWindowFunction {
     int numRows = rows.size();
 
     if (_windowFrame.isUnboundedPreceding() && 
_windowFrame.isUnboundedFollowing()) {
-      // Find the first non-null value and fill it in all rows
-      int indexOfFirstNonNullValue = indexOfFirstNonNullValueInWindow(rows, 0, 
numRows - 1);
-      if (indexOfFirstNonNullValue == -1) {
-        // There's no non-null value
-        return Collections.nCopies(numRows, null);
-      } else {
-        return fillAllWithValue(rows, 
extractValueFromRow(rows.get(indexOfFirstNonNullValue)));
-      }
+      return processUnboundedWindowIgnoreNulls(rows);
     }
 
     if (_windowFrame.isUnboundedPreceding() && 
_windowFrame.isUpperBoundCurrentRow()) {
@@ -270,6 +269,18 @@ public class FirstValueWindowFunction extends 
ValueWindowFunction {
     throw new IllegalStateException("RANGE window frame with offset PRECEDING 
/ FOLLOWING is not supported");
   }
 
+  private List<Object> processUnboundedWindowIgnoreNulls(List<Object[]> rows) {
+    int numRows = rows.size();
+    // Find the first non-null value and fill it in all rows
+    int indexOfFirstNonNullValue = indexOfFirstNonNullValueInWindow(rows, 0, 
numRows - 1);
+    if (indexOfFirstNonNullValue == -1) {
+      // There's no non-null value
+      return Collections.nCopies(numRows, null);
+    } else {
+      return Collections.nCopies(numRows, 
extractValueFromRow(rows.get(indexOfFirstNonNullValue)));
+    }
+  }
+
   /**
    * Both lowerBound and upperBound should be valid values for the given row 
set. The returned value is -1 if there is
    * no non-null value in the window.
diff --git 
a/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/LastValueWindowFunction.java
 
b/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/LastValueWindowFunction.java
index 5383525d2d..8da5fa6fb1 100644
--- 
a/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/LastValueWindowFunction.java
+++ 
b/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/LastValueWindowFunction.java
@@ -60,7 +60,7 @@ public class LastValueWindowFunction extends 
ValueWindowFunction {
   private List<Object> processRowsWindow(List<Object[]> rows) {
     int numRows = rows.size();
     if (_windowFrame.isUnboundedFollowing() && _windowFrame.getLowerBound() <= 
0) {
-      return fillAllWithValue(rows, extractValueFromRow(rows.get(numRows - 
1)));
+      return Collections.nCopies(numRows, extractValueFromRow(rows.get(numRows 
- 1)));
     }
 
     List<Object> result = new ArrayList<>(numRows);
@@ -92,6 +92,10 @@ public class LastValueWindowFunction extends 
ValueWindowFunction {
   }
 
   private List<Object> processRowsWindowIgnoreNulls(List<Object[]> rows) {
+    if (_windowFrame.isUnboundedPreceding() && 
_windowFrame.isUnboundedFollowing()) {
+      return processUnboundedWindowIgnoreNulls(rows);
+    }
+
     int numRows = rows.size();
     int lowerBound = _windowFrame.getLowerBound();
     int upperBound = Math.min(_windowFrame.getUpperBound(), numRows - 1);
@@ -142,7 +146,7 @@ public class LastValueWindowFunction extends 
ValueWindowFunction {
   private List<Object> processRangeWindow(List<Object[]> rows) {
     int numRows = rows.size();
     if (_windowFrame.isUnboundedFollowing()) {
-      return fillAllWithValue(rows, extractValueFromRow(rows.get(numRows - 
1)));
+      return Collections.nCopies(numRows, extractValueFromRow(rows.get(numRows 
- 1)));
     }
 
     // The upper bound has to be CURRENT ROW here since we don't support RANGE 
windows with offset value
@@ -177,14 +181,7 @@ public class LastValueWindowFunction extends 
ValueWindowFunction {
     int numRows = rows.size();
 
     if (_windowFrame.isUnboundedPreceding() && 
_windowFrame.isUnboundedFollowing()) {
-      // Find the last non-null value and fill it in all rows
-      int indexOfLastNonNullValue = indexOfLastNonNullValueInWindow(rows, 0, 
numRows - 1);
-      if (indexOfLastNonNullValue == -1) {
-        // There's no non-null value
-        return Collections.nCopies(numRows, null);
-      } else {
-        return fillAllWithValue(rows, 
extractValueFromRow(rows.get(indexOfLastNonNullValue)));
-      }
+      return processUnboundedWindowIgnoreNulls(rows);
     }
 
     if (_windowFrame.isUnboundedPreceding() && 
_windowFrame.isUpperBoundCurrentRow()) {
@@ -259,6 +256,18 @@ public class LastValueWindowFunction extends 
ValueWindowFunction {
     throw new IllegalStateException("RANGE window frame with offset PRECEDING 
/ FOLLOWING is not supported");
   }
 
+  private List<Object> processUnboundedWindowIgnoreNulls(List<Object[]> rows) {
+    int numRows = rows.size();
+    // Find the last non-null value and fill it in all rows
+    int indexOfLastNonNullValue = indexOfLastNonNullValueInWindow(rows, 0, 
numRows - 1);
+    if (indexOfLastNonNullValue == -1) {
+      // There's no non-null value
+      return Collections.nCopies(numRows, null);
+    } else {
+      return Collections.nCopies(numRows, 
extractValueFromRow(rows.get(indexOfLastNonNullValue)));
+    }
+  }
+
   /**
    * Both lowerBound and upperBound should be valid values for the given row 
set. The returned value is -1 if there is
    * no non-null value in the window.
diff --git 
a/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/ValueWindowFunction.java
 
b/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/ValueWindowFunction.java
index ce8a00d432..154c846766 100644
--- 
a/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/ValueWindowFunction.java
+++ 
b/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/window/value/ValueWindowFunction.java
@@ -19,7 +19,6 @@
 package org.apache.pinot.query.runtime.operator.window.value;
 
 import com.google.common.collect.ImmutableMap;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import org.apache.calcite.rel.RelFieldCollation;
@@ -48,10 +47,4 @@ public abstract class ValueWindowFunction extends 
WindowFunction {
     super(aggCall, inputSchema, collations, windowFrame);
     _ignoreNulls = aggCall.isIgnoreNulls();
   }
-
-  protected List<Object> fillAllWithValue(List<Object[]> rows, Object value) {
-    int numRows = rows.size();
-    assert numRows > 0;
-    return Collections.nCopies(numRows, value);
-  }
 }


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

Reply via email to