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 5796ad2141 Fix window frame upper bound offset extraction in
PinotWindowExchangeNodeInsertRule (#14304)
5796ad2141 is described below
commit 5796ad2141b93475adc59664c280849f88091405
Author: Yash Mayya <[email protected]>
AuthorDate: Mon Oct 28 04:50:07 2024 +0530
Fix window frame upper bound offset extraction in
PinotWindowExchangeNodeInsertRule (#14304)
---
.../rules/PinotWindowExchangeNodeInsertRule.java | 2 +-
.../PinotWindowExchangeNodeInsertRuleTest.java | 127 +++++++++++++++++++++
2 files changed, 128 insertions(+), 1 deletion(-)
diff --git
a/pinot-query-planner/src/main/java/org/apache/pinot/calcite/rel/rules/PinotWindowExchangeNodeInsertRule.java
b/pinot-query-planner/src/main/java/org/apache/pinot/calcite/rel/rules/PinotWindowExchangeNodeInsertRule.java
index 6d3f7b99b7..78c8da3d8e 100644
---
a/pinot-query-planner/src/main/java/org/apache/pinot/calcite/rel/rules/PinotWindowExchangeNodeInsertRule.java
+++
b/pinot-query-planner/src/main/java/org/apache/pinot/calcite/rel/rules/PinotWindowExchangeNodeInsertRule.java
@@ -202,7 +202,7 @@ public class PinotWindowExchangeNodeInsertRule extends
RelOptRule {
throw new IllegalStateException(
"Could not read window upper bound literal value from window
group: " + oldWindowGroup);
}
- upperBound = lowerBound.isFollowing() ?
RexWindowBounds.following(literal) : RexWindowBounds.preceding(literal);
+ upperBound = upperBound.isFollowing() ?
RexWindowBounds.following(literal) : RexWindowBounds.preceding(literal);
windowChanged = true;
}
diff --git
a/pinot-query-planner/src/test/java/org/apache/pinot/calcite/rel/rules/PinotWindowExchangeNodeInsertRuleTest.java
b/pinot-query-planner/src/test/java/org/apache/pinot/calcite/rel/rules/PinotWindowExchangeNodeInsertRuleTest.java
new file mode 100644
index 0000000000..cf8a5f33ce
--- /dev/null
+++
b/pinot-query-planner/src/test/java/org/apache/pinot/calcite/rel/rules/PinotWindowExchangeNodeInsertRuleTest.java
@@ -0,0 +1,127 @@
+/**
+ * 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.calcite.rel.rules;
+
+import java.util.Collections;
+import java.util.List;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptRuleCall;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.plan.hep.HepRelVertex;
+import org.apache.calcite.rel.RelCollations;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Window;
+import org.apache.calcite.rel.logical.LogicalProject;
+import org.apache.calcite.rel.logical.LogicalWindow;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.rex.RexInputRef;
+import org.apache.calcite.rex.RexLiteral;
+import org.apache.calcite.rex.RexWindowBounds;
+import org.apache.calcite.sql.fun.SqlSumAggFunction;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.pinot.query.planner.logical.RexExpressionUtils;
+import org.apache.pinot.query.type.TypeFactory;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+
+public class PinotWindowExchangeNodeInsertRuleTest {
+ private static final TypeFactory TYPE_FACTORY = new TypeFactory();
+ private static final RexBuilder REX_BUILDER = new RexBuilder(TYPE_FACTORY);
+
+ private AutoCloseable _mocks;
+
+ @Mock
+ private RelOptRuleCall _call;
+ @Mock
+ private HepRelVertex _input;
+ @Mock
+ private RelOptCluster _cluster;
+
+ @BeforeMethod
+ public void setUp() {
+ _mocks = MockitoAnnotations.openMocks(this);
+ RelTraitSet traits = RelTraitSet.createEmpty();
+ Mockito.when(_input.getTraitSet()).thenReturn(traits);
+ Mockito.when(_input.getCluster()).thenReturn(_cluster);
+ }
+
+ @AfterMethod
+ public void tearDown()
+ throws Exception {
+ _mocks.close();
+ }
+
+ @Test
+ public void testLiteralWindowOffsetBoundsExtraction() {
+ // Create a RelOptRuleCall for a window with offset lower and upper bounds
and test the extraction of the bounds
+ RelDataType intType = TYPE_FACTORY.createSqlType(SqlTypeName.INTEGER);
+
+ RexInputRef windowFunctionInputRef = Mockito.mock(RexInputRef.class);
+ Mockito.when(windowFunctionInputRef.getIndex()).thenReturn(0);
+ Mockito.when(windowFunctionInputRef.getType()).thenReturn(intType);
+ RexInputRef partitionColInputRef = Mockito.mock(RexInputRef.class);
+ Mockito.when(partitionColInputRef.getIndex()).thenReturn(1);
+ Mockito.when(partitionColInputRef.getType()).thenReturn(intType);
+ RexInputRef orderColInputRef = Mockito.mock(RexInputRef.class);
+ Mockito.when(orderColInputRef.getIndex()).thenReturn(2);
+ Mockito.when(orderColInputRef.getType()).thenReturn(intType);
+ RexInputRef lowerBoundInputRef = Mockito.mock(RexInputRef.class);
+ Mockito.when(lowerBoundInputRef.getIndex()).thenReturn(3);
+ Mockito.when(lowerBoundInputRef.getType()).thenReturn(intType);
+ RexInputRef upperBoundInputRef = Mockito.mock(RexInputRef.class);
+ Mockito.when(upperBoundInputRef.getIndex()).thenReturn(4);
+ Mockito.when(upperBoundInputRef.getType()).thenReturn(intType);
+
+ List<Window.Group> groups = Collections.singletonList(
+ new Window.Group(ImmutableBitSet.of(List.of(1)), true,
RexWindowBounds.preceding(lowerBoundInputRef),
+ RexWindowBounds.following(upperBoundInputRef),
RelCollations.of(2), List.of(
+ new Window.RexWinAggCall(new SqlSumAggFunction(intType), intType,
List.of(windowFunctionInputRef), 0, false,
+ false))));
+
+ List<RexLiteral> literals = List.of(REX_BUILDER.makeLiteral(5, intType),
REX_BUILDER.makeLiteral(10, intType));
+ LogicalWindow originalWindow =
LogicalWindow.create(RelTraitSet.createEmpty(), _input, literals, intType,
groups);
+
+ LogicalProject inputProject = Mockito.mock(LogicalProject.class);
+ RelDataType projectDataType = Mockito.mock(RelDataType.class);
+ Mockito.when(projectDataType.getFieldCount()).thenReturn(3);
+ Mockito.when(inputProject.getRowType()).thenReturn(projectDataType);
+ Mockito.when(inputProject.getProjects())
+ .thenReturn(List.of(windowFunctionInputRef, partitionColInputRef,
orderColInputRef));
+ Mockito.when(_input.getCurrentRel()).thenReturn(inputProject);
+ Mockito.when(_call.rel(0)).thenReturn(originalWindow);
+ PinotWindowExchangeNodeInsertRule.INSTANCE.onMatch(_call);
+
+ ArgumentCaptor<RelNode> logicalWindowCapture =
ArgumentCaptor.forClass(LogicalWindow.class);
+ Mockito.verify(_call,
Mockito.times(1)).transformTo(logicalWindowCapture.capture());
+ LogicalWindow newWindow = (LogicalWindow) logicalWindowCapture.getValue();
+
Assert.assertEquals(RexExpressionUtils.getValueAsInt(newWindow.groups.get(0).lowerBound.getOffset()),
5);
+ Assert.assertTrue(newWindow.groups.get(0).lowerBound.isPreceding());
+
Assert.assertEquals(RexExpressionUtils.getValueAsInt(newWindow.groups.get(0).upperBound.getOffset()),
10);
+ Assert.assertTrue(newWindow.groups.get(0).upperBound.isFollowing());
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]