You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ja...@apache.org on 2022/05/30 08:27:41 UTC
[iotdb] 01/01: [IOTDB-3319] fix IndexOutOfBoundsException when executing linear fill in group by query
This is an automated email from the ASF dual-hosted git repository.
jackietien pushed a commit to branch IOTDB-3319
in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 3e56d5831613907ef4d3e8e5c1ba7c2216654435
Author: JackieTien97 <ja...@gmail.com>
AuthorDate: Mon May 30 16:27:04 2022 +0800
[IOTDB-3319] fix IndexOutOfBoundsException when executing linear fill in group by query
---
.../operator/process/LinearFillOperator.java | 3 +-
.../execution/operator/LinearFillOperatorTest.java | 113 ++++++++++++++++++++-
2 files changed, 111 insertions(+), 5 deletions(-)
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/process/LinearFillOperator.java b/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/process/LinearFillOperator.java
index 35277da1ae..dbbe1b638a 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/process/LinearFillOperator.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/process/LinearFillOperator.java
@@ -125,7 +125,8 @@ public class LinearFillOperator implements ProcessOperator {
TsBlock result =
new TsBlock(originTsBlock.getPositionCount(), originTsBlock.getTimeColumn(), columns);
for (int i = 0; i < outputColumnCount; i++) {
- nextTsBlockIndex[i]--;
+ // make sure nextTsBlockIndex for each column >= 1
+ nextTsBlockIndex[i] = Math.max(1, nextTsBlockIndex[i] - 1);
}
return result;
}
diff --git a/server/src/test/java/org/apache/iotdb/db/mpp/execution/operator/LinearFillOperatorTest.java b/server/src/test/java/org/apache/iotdb/db/mpp/execution/operator/LinearFillOperatorTest.java
index 6c17c09d4f..2fb9898418 100644
--- a/server/src/test/java/org/apache/iotdb/db/mpp/execution/operator/LinearFillOperatorTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/mpp/execution/operator/LinearFillOperatorTest.java
@@ -233,8 +233,8 @@ public class LinearFillOperatorTest {
}
assertTrue(fillOperator.isFinished());
- assertEquals(3, count);
- assertEquals(4, nullBlockIndex);
+ assertEquals(res.length, count);
+ assertEquals(nullBlock.length, nullBlockIndex);
} finally {
instanceNotificationExecutor.shutdown();
@@ -431,8 +431,113 @@ public class LinearFillOperatorTest {
}
assertTrue(fillOperator.isFinished());
- assertEquals(3, count);
- assertEquals(5, nullBlockIndex);
+ assertEquals(res.length, count);
+ assertEquals(nullBlock.length, nullBlockIndex);
+
+ } finally {
+ instanceNotificationExecutor.shutdown();
+ }
+ }
+
+ @Test
+ public void batchLinearFillTest3() {
+ ExecutorService instanceNotificationExecutor =
+ IoTDBThreadPoolFactory.newFixedThreadPool(1, "test-instance-notification");
+ try {
+ QueryId queryId = new QueryId("stub_query");
+ FragmentInstanceId instanceId =
+ new FragmentInstanceId(new PlanFragmentId(queryId, 0), "stub-instance");
+ FragmentInstanceStateMachine stateMachine =
+ new FragmentInstanceStateMachine(instanceId, instanceNotificationExecutor);
+ FragmentInstanceContext fragmentInstanceContext =
+ createFragmentInstanceContext(instanceId, stateMachine);
+ PlanNodeId planNodeId1 = new PlanNodeId("1");
+ fragmentInstanceContext.addOperatorContext(
+ 1, planNodeId1, LinearFillOperator.class.getSimpleName());
+
+ LinearFill[] fillArray = new LinearFill[] {new FloatLinearFill()};
+ LinearFillOperator fillOperator =
+ new LinearFillOperator(
+ fragmentInstanceContext.getOperatorContexts().get(0),
+ fillArray,
+ new Operator() {
+ private int index = 0;
+ private final float[][][] value =
+ new float[][][] {
+ {{0.0f}}, {{2.0f}}, {{3.0f}}, {{4.0f}}, {{0.0f}}, {{0.0f}}, {{0.0f}}
+ };
+ final boolean[][][] isNull =
+ new boolean[][][] {
+ {{true}}, {{false}}, {{false}}, {{false}}, {{true}}, {{true}}, {{true}}
+ };
+
+ @Override
+ public OperatorContext getOperatorContext() {
+ return null;
+ }
+
+ @Override
+ public TsBlock next() {
+ TsBlockBuilder builder = new TsBlockBuilder(ImmutableList.of(TSDataType.FLOAT));
+ for (int i = 0; i < 1; i++) {
+ builder.getTimeColumnBuilder().writeLong(i + index);
+ for (int j = 0; j < 1; j++) {
+ if (isNull[index][i][j]) {
+ builder.getColumnBuilder(j).appendNull();
+ } else {
+ builder.getColumnBuilder(j).writeFloat(value[index][i][j]);
+ }
+ }
+ builder.declarePosition();
+ }
+ index++;
+ return builder.build();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return index < 7;
+ }
+
+ @Override
+ public boolean isFinished() {
+ return index >= 7;
+ }
+ });
+
+ int count = 0;
+ float[][][] res =
+ new float[][][] {{{0.0f}}, {{2.0f}}, {{3.0f}}, {{4.0f}}, {{0.0f}}, {{0.0f}}, {{0.0f}}};
+ boolean[][][] isNull =
+ new boolean[][][] {
+ {{true}}, {{false}}, {{false}}, {{false}}, {{true}}, {{true}}, {{true}}
+ };
+
+ boolean[] nullBlock =
+ new boolean[] {true, false, false, false, false, true, true, true, false, false, false};
+ int nullBlockIndex = 0;
+ while (fillOperator.hasNext()) {
+ TsBlock block = fillOperator.next();
+ assertEquals(nullBlock[nullBlockIndex++], block == null);
+ if (block == null) {
+ continue;
+ }
+ for (int i = 0; i < block.getPositionCount(); i++) {
+ long expectedTime = i + count;
+ assertEquals(expectedTime, block.getTimeByIndex(i));
+ for (int j = 0; j < 1; j++) {
+ assertEquals(isNull[count][i][j], block.getColumn(j).isNull(i));
+ if (!isNull[count][i][j]) {
+ assertEquals(res[count][i][j], block.getColumn(j).getFloat(i), 0.00001f);
+ }
+ }
+ }
+ count++;
+ }
+
+ assertTrue(fillOperator.isFinished());
+ assertEquals(res.length, count);
+ assertEquals(nullBlock.length, nullBlockIndex);
} finally {
instanceNotificationExecutor.shutdown();