This is an automated email from the ASF dual-hosted git repository. jackietien pushed a commit to branch IOTDB-3364 in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 7ea03463fca72e6756d4a99d5d0e75b48e703bdd Author: JackieTien97 <[email protected]> AuthorDate: Wed Jun 1 12:28:34 2022 +0800 [IOTDB-3364] Fix Query stucked with null valued aligned timeseries bug --- .../db/integration/aligned/IoTDBEmptyDataIT.java | 86 ++++++++++++++++++++++ .../querycontext/AlignedReadOnlyMemChunk.java | 13 +++- .../file/metadata/statistics/Statistics.java | 20 ++--- 3 files changed, 106 insertions(+), 13 deletions(-) diff --git a/integration/src/test/java/org/apache/iotdb/db/integration/aligned/IoTDBEmptyDataIT.java b/integration/src/test/java/org/apache/iotdb/db/integration/aligned/IoTDBEmptyDataIT.java new file mode 100644 index 0000000000..865b1cfc7f --- /dev/null +++ b/integration/src/test/java/org/apache/iotdb/db/integration/aligned/IoTDBEmptyDataIT.java @@ -0,0 +1,86 @@ +/* + * 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.iotdb.db.integration.aligned; + +import org.apache.iotdb.db.utils.EnvironmentUtils; +import org.apache.iotdb.jdbc.Config; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +public class IoTDBEmptyDataIT { + + @BeforeClass + public static void setUp() throws Exception { + EnvironmentUtils.envSetUp(); + Class.forName(Config.JDBC_DRIVER_NAME); + try (Connection connection = + DriverManager.getConnection( + Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root", "root"); + Statement statement = connection.createStatement()) { + + statement.execute("create aligned timeseries root.sg.d1(s1 int32);"); + statement.execute("insert into root.sg.d1(time, s1) aligned values(1400, null); "); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @AfterClass + public static void tearDown() throws Exception { + EnvironmentUtils.cleanEnv(); + } + + @Test + public void selectAllAlignedWithoutValueFilterTest() throws ClassNotFoundException { + + Class.forName(Config.JDBC_DRIVER_NAME); + try (Connection connection = + DriverManager.getConnection( + Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root", "root"); + Statement statement = connection.createStatement()) { + + boolean hasResultSet = statement.execute("select * from root.sg.d1"); + Assert.assertTrue(hasResultSet); + + try (ResultSet resultSet = statement.getResultSet()) { + int cnt = 0; + while (resultSet.next()) { + cnt++; + } + assertEquals(0, cnt); + } + + } catch (SQLException e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } +} diff --git a/server/src/main/java/org/apache/iotdb/db/engine/querycontext/AlignedReadOnlyMemChunk.java b/server/src/main/java/org/apache/iotdb/db/engine/querycontext/AlignedReadOnlyMemChunk.java index 14dd30b7e2..7641235e51 100644 --- a/server/src/main/java/org/apache/iotdb/db/engine/querycontext/AlignedReadOnlyMemChunk.java +++ b/server/src/main/java/org/apache/iotdb/db/engine/querycontext/AlignedReadOnlyMemChunk.java @@ -82,9 +82,6 @@ public class AlignedReadOnlyMemChunk extends ReadOnlyMemChunk { for (int column = 0; column < tsBlock.getValueColumnCount(); column++) { Statistics valueStatistics = Statistics.getStatsByType(dataTypes.get(column)); valueStatistics.setEmpty(true); - IChunkMetadata valueChunkMetadata = - new ChunkMetadata(valueChunkNames.get(column), dataTypes.get(column), 0, valueStatistics); - valueChunkMetadataList.add(valueChunkMetadata); switch (dataTypes.get(column)) { case BOOLEAN: for (int row = 0; row < tsBlock.getPositionCount(); row++) { @@ -137,7 +134,15 @@ public class AlignedReadOnlyMemChunk extends ReadOnlyMemChunk { default: throw new QueryProcessException("Unsupported data type:" + dataTypes.get(column)); } - valueStatistics.setEmpty(false); + if (valueStatistics.getCount() > 0) { + IChunkMetadata valueChunkMetadata = + new ChunkMetadata( + valueChunkNames.get(column), dataTypes.get(column), 0, valueStatistics); + valueChunkMetadataList.add(valueChunkMetadata); + valueStatistics.setEmpty(false); + } else { + valueChunkMetadataList.add(null); + } } IChunkMetadata alignedChunkMetadata = new AlignedChunkMetadata(timeChunkMetadata, valueChunkMetadataList); diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/statistics/Statistics.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/statistics/Statistics.java index a9fcec1b2a..012fbe729d 100644 --- a/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/statistics/Statistics.java +++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/file/metadata/statistics/Statistics.java @@ -155,16 +155,18 @@ public abstract class Statistics<T extends Serializable> { @SuppressWarnings("unchecked") public void mergeStatistics(Statistics<? extends Serializable> stats) { if (this.getClass() == stats.getClass()) { - if (stats.startTime < this.startTime) { - this.startTime = stats.startTime; + if (!stats.isEmpty) { + if (stats.startTime < this.startTime) { + this.startTime = stats.startTime; + } + if (stats.endTime > this.endTime) { + this.endTime = stats.endTime; + } + // must be sure no overlap between two statistics + this.count += stats.count; + mergeStatisticsValue((Statistics<T>) stats); + isEmpty = false; } - if (stats.endTime > this.endTime) { - this.endTime = stats.endTime; - } - // must be sure no overlap between two statistics - this.count += stats.count; - mergeStatisticsValue((Statistics<T>) stats); - isEmpty = false; } else { Class<?> thisClass = this.getClass(); Class<?> statsClass = stats.getClass();
