Skip to content

Commit 63dfac8

Browse files
authored
Fix window function state reset across batches (#17813)
1 parent 594fb87 commit 63dfac8

3 files changed

Lines changed: 105 additions & 2 deletions

File tree

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.iotdb.relational.it.db.it;
21+
22+
import org.apache.iotdb.it.env.EnvFactory;
23+
import org.apache.iotdb.it.framework.IoTDBTestRunner;
24+
import org.apache.iotdb.itbase.category.TableClusterIT;
25+
import org.apache.iotdb.itbase.category.TableLocalStandaloneIT;
26+
27+
import org.junit.AfterClass;
28+
import org.junit.BeforeClass;
29+
import org.junit.Test;
30+
import org.junit.experimental.categories.Category;
31+
import org.junit.runner.RunWith;
32+
33+
import java.sql.Connection;
34+
import java.sql.Statement;
35+
36+
import static org.apache.iotdb.db.it.utils.TestUtils.tableResultSetEqualTest;
37+
import static org.junit.Assert.fail;
38+
39+
@RunWith(IoTDBTestRunner.class)
40+
@Category({TableLocalStandaloneIT.class, TableClusterIT.class})
41+
public class IoTDBWindowFunctionBatchedResultIT {
42+
private static final String DATABASE_NAME = "test";
43+
44+
private static final String[] SQLS =
45+
new String[] {
46+
"CREATE DATABASE " + DATABASE_NAME,
47+
"USE " + DATABASE_NAME,
48+
"CREATE TABLE batched_rank (device STRING TAG, value INT32 FIELD)",
49+
"INSERT INTO batched_rank VALUES (2021-01-01T00:00:01, 'd1', 1)",
50+
"INSERT INTO batched_rank VALUES (2021-01-01T00:00:02, 'd1', 2)",
51+
"INSERT INTO batched_rank VALUES (2021-01-01T00:00:03, 'd1', 3)",
52+
"INSERT INTO batched_rank VALUES (2021-01-01T00:00:04, 'd1', 4)",
53+
"INSERT INTO batched_rank VALUES (2021-01-01T00:00:05, 'd1', 5)",
54+
"FLUSH",
55+
"CLEAR ATTRIBUTE CACHE",
56+
};
57+
58+
@BeforeClass
59+
public static void setUp() {
60+
EnvFactory.getEnv().getConfig().getCommonConfig().setMaxTsBlockLineNumber(2);
61+
EnvFactory.getEnv().initClusterEnvironment();
62+
insertData();
63+
}
64+
65+
@AfterClass
66+
public static void tearDown() {
67+
EnvFactory.getEnv().cleanClusterEnvironment();
68+
}
69+
70+
@Test
71+
public void testRankStateAcrossOutputBatches() {
72+
String[] expectedHeader = new String[] {"value", "rk"};
73+
String[] retArray =
74+
new String[] {
75+
"1,1,", "2,2,", "3,3,", "4,4,", "5,5,",
76+
};
77+
tableResultSetEqualTest(
78+
"SELECT value, rank() OVER (PARTITION BY device ORDER BY value) AS rk FROM batched_rank ORDER BY value",
79+
expectedHeader,
80+
retArray,
81+
DATABASE_NAME);
82+
}
83+
84+
private static void insertData() {
85+
try (Connection connection = EnvFactory.getEnv().getTableConnection();
86+
Statement statement = connection.createStatement()) {
87+
for (String sql : SQLS) {
88+
statement.execute(sql);
89+
}
90+
} catch (Exception e) {
91+
fail("insertData failed.");
92+
}
93+
}
94+
}

iotdb-core/calc-commons/src/main/java/org/apache/iotdb/calc/execution/operator/process/window/TableWindowOperator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ private void finalizeCurrentPartition() {
218218
private TsBlock transform(long startTime) {
219219
while (!cachedPartitionExecutors.isEmpty()) {
220220
PartitionExecutor partitionExecutor = cachedPartitionExecutors.getFirst();
221-
partitionExecutor.resetWindowFunctions();
221+
partitionExecutor.initializeWindowFunctions();
222222

223223
while (System.nanoTime() - startTime < maxRuntime
224224
&& !tsBlockBuilder.isFull()

iotdb-core/calc-commons/src/main/java/org/apache/iotdb/calc/execution/operator/process/window/partition/PartitionExecutor.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public final class PartitionExecutor {
5959
private final List<Frame> frames;
6060

6161
private final boolean needPeerGroup;
62+
private boolean windowFunctionsInitialized;
6263

6364
public PartitionExecutor(
6465
List<TsBlock> tsBlocks,
@@ -114,6 +115,7 @@ private PartitionExecutor(
114115
sortedColumns = partition.getSortedColumnList(sortChannels);
115116

116117
currentPosition = partitionStart;
118+
windowFunctionsInitialized = false;
117119
needPeerGroup =
118120
windowFunctions.stream().anyMatch(WindowFunction::needPeerGroup)
119121
|| frameInfoList.stream()
@@ -212,9 +214,16 @@ private void updatePeerGroup() {
212214
}
213215
}
214216

215-
public void resetWindowFunctions() {
217+
private void resetWindowFunctions() {
216218
for (WindowFunction windowFunction : windowFunctions) {
217219
windowFunction.reset();
218220
}
219221
}
222+
223+
public void initializeWindowFunctions() {
224+
if (!windowFunctionsInitialized) {
225+
resetWindowFunctions();
226+
windowFunctionsInitialized = true;
227+
}
228+
}
220229
}

0 commit comments

Comments
 (0)