This is an automated email from the ASF dual-hosted git repository. jackietien pushed a commit to branch force_ci/object_type in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 50dd71436ec44fe2b03cedb25e074906d402f493 Author: Caideyipi <[email protected]> AuthorDate: Fri Nov 21 14:45:14 2025 +0800 Fixed the bug related to "Fixed the bugs related to device auto-create alignment ignorance" (#16781) * gsa * ff * ff (cherry picked from commit c76c5fe3d5a43d5a4a3f5e82b1f42b2699d240fe) --- .../org/apache/iotdb/db/it/IoTDBLoadTsFileIT.java | 102 +++++++++++++++++++++ .../metadata/AlignedTimeSeriesException.java | 35 ------- .../load/TreeSchemaAutoCreatorAndVerifier.java | 4 + .../analyze/schema/AutoCreateSchemaExecutor.java | 9 +- 4 files changed, 113 insertions(+), 37 deletions(-) diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBLoadTsFileIT.java b/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBLoadTsFileIT.java index c54adb34711..928c7875b19 100644 --- a/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBLoadTsFileIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBLoadTsFileIT.java @@ -263,6 +263,108 @@ public class IoTDBLoadTsFileIT { } } + @Test + // Shall succeed with tablet conversion + public void testLoadWithAlignmentMismatch() throws Exception { + registerSchema(); + + final long writtenPoint1; + // device 0, sg 0 + try (final TsFileGenerator generator = + new TsFileGenerator(new File(tmpDir, "1-0-0-0.tsfile"))) { + // Wrong, with 04-07 non-exist + generator.registerAlignedTimeseries( + SchemaConfig.DEVICE_0, + Arrays.asList( + SchemaConfig.MEASUREMENT_00, + SchemaConfig.MEASUREMENT_01, + SchemaConfig.MEASUREMENT_02, + SchemaConfig.MEASUREMENT_03, + SchemaConfig.MEASUREMENT_04, + SchemaConfig.MEASUREMENT_05, + SchemaConfig.MEASUREMENT_06, + SchemaConfig.MEASUREMENT_07)); + generator.generateData(SchemaConfig.DEVICE_0, 100000, PARTITION_INTERVAL / 10_000, false); + writtenPoint1 = generator.getTotalNumber(); + } + + final long writtenPoint2; + // device 2, device 3, device4, sg 1 + try (final TsFileGenerator generator = + new TsFileGenerator(new File(tmpDir, "2-0-0-0.tsfile"))) { + // right + generator.registerTimeseries( + SchemaConfig.DEVICE_2, Collections.singletonList(SchemaConfig.MEASUREMENT_20)); + // right + generator.registerTimeseries( + SchemaConfig.DEVICE_3, Collections.singletonList(SchemaConfig.MEASUREMENT_30)); + // Wrong, with 06 non-exist + generator.registerTimeseries( + SchemaConfig.DEVICE_4, + Arrays.asList(SchemaConfig.MEASUREMENT_40, SchemaConfig.MEASUREMENT_06)); + generator.generateData(SchemaConfig.DEVICE_2, 10000, PARTITION_INTERVAL / 10_000, false); + generator.generateData(SchemaConfig.DEVICE_3, 10000, PARTITION_INTERVAL / 10_000, false); + generator.generateData(SchemaConfig.DEVICE_4, 10000, PARTITION_INTERVAL / 10_000, true); + for (int i = 0; i < 1000; i++) { + generator.generateData(SchemaConfig.DEVICE_4, 1, PARTITION_INTERVAL - 10, true); + } + writtenPoint2 = generator.getTotalNumber(); + } + + try (final Connection connection = EnvFactory.getEnv().getConnection(); + final Statement statement = connection.createStatement()) { + + try { + statement.execute( + String.format( + "load \"%s\" with ('database-level'='2', 'convert-on-type-mismatch'='false')", + tmpDir.getAbsolutePath() + File.separator + "1-0-0-0.tsfile")); + Assert.fail(); + } catch (final Exception e) { + Assert.assertTrue( + e.getMessage() + .contains( + "TimeSeries under this device is not aligned, please use createTimeSeries or change device. (Path: root.sg.test_0.d_0).")); + } + + try { + statement.execute( + String.format( + "load \"%s\" with ('database-level'='2', 'convert-on-type-mismatch'='false')", + tmpDir.getAbsolutePath() + File.separator + "2-0-0-0.tsfile")); + Assert.fail(); + } catch (final Exception e) { + Assert.assertTrue( + e.getMessage() + .contains( + "TimeSeries under this device is aligned, please use createAlignedTimeSeries or change device. (Path: root.sg.test_1.a_4).")); + } + + statement.execute(String.format("load \"%s\" sglevel=2", tmpDir.getAbsolutePath())); + + try (final ResultSet resultSet = + statement.executeQuery("select count(*) from root.sg.** group by level=1,2")) { + if (resultSet.next()) { + long sg1Count = resultSet.getLong("count(root.sg.test_0.*.*)"); + Assert.assertEquals(writtenPoint1, sg1Count); + long sg2Count = resultSet.getLong("count(root.sg.test_1.*.*)"); + Assert.assertEquals(writtenPoint2, sg2Count); + } else { + Assert.fail("This ResultSet is empty."); + } + } + } + + // Try to delete after loading. Expect no deadlock + try (final Connection connection = EnvFactory.getEnv().getConnection(); + final Statement statement = connection.createStatement()) { + statement.execute( + String.format( + "delete timeseries %s.%s", + SchemaConfig.DEVICE_0, SchemaConfig.MEASUREMENT_00.getMeasurementName())); + } + } + @Test public void testLoadAcrossMultipleTimePartitions() throws Exception { registerSchema(); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/metadata/AlignedTimeSeriesException.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/metadata/AlignedTimeSeriesException.java deleted file mode 100644 index f159376dfae..00000000000 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/metadata/AlignedTimeSeriesException.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.exception.metadata; - -import org.apache.iotdb.commons.exception.MetadataException; -import org.apache.iotdb.rpc.TSStatusCode; - -public class AlignedTimeSeriesException extends MetadataException { - - public AlignedTimeSeriesException(final boolean aligned, final String path) { - super( - String.format( - "TimeSeries under this device is%s aligned, please use createTimeSeries or change device. (Path: %s)", - aligned ? "" : " not", path), - TSStatusCode.ALIGNED_TIMESERIES_ERROR.getStatusCode(), - true); - } -} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/TreeSchemaAutoCreatorAndVerifier.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/TreeSchemaAutoCreatorAndVerifier.java index f0412c36bb8..c174bd7942b 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/TreeSchemaAutoCreatorAndVerifier.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/TreeSchemaAutoCreatorAndVerifier.java @@ -235,6 +235,10 @@ public class TreeSchemaAutoCreatorAndVerifier { handleException(e, loadTsFileAnalyzer.getStatementString()); } } catch (Exception e) { + if (e.getCause() instanceof LoadAnalyzeTypeMismatchException + && loadTsFileAnalyzer.isConvertOnTypeMismatch()) { + throw (LoadAnalyzeTypeMismatchException) e.getCause(); + } handleException(e, loadTsFileAnalyzer.getStatementString()); } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/schema/AutoCreateSchemaExecutor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/schema/AutoCreateSchemaExecutor.java index a6a3301aea0..61d58310d7a 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/schema/AutoCreateSchemaExecutor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/schema/AutoCreateSchemaExecutor.java @@ -29,7 +29,7 @@ import org.apache.iotdb.commons.service.metric.PerformanceOverviewMetrics; import org.apache.iotdb.db.auth.AuthorityChecker; import org.apache.iotdb.db.conf.IoTDBConfig; import org.apache.iotdb.db.conf.IoTDBDescriptor; -import org.apache.iotdb.db.exception.metadata.AlignedTimeSeriesException; +import org.apache.iotdb.db.exception.load.LoadAnalyzeTypeMismatchException; import org.apache.iotdb.db.exception.sql.SemanticException; import org.apache.iotdb.db.protocol.session.SessionManager; import org.apache.iotdb.db.queryengine.common.MPPQueryContext; @@ -534,7 +534,12 @@ class AutoCreateSchemaExecutor { } else { // Load does not tolerate the device alignment mismatch throw new SemanticException( - new AlignedTimeSeriesException(!pair.getLeft(), devicePath.getFullPath())); + new LoadAnalyzeTypeMismatchException( + String.format( + "TimeSeries under this device is%s aligned, please use create%sTimeSeries or change device. (Path: %s)", + !pair.getLeft() ? "" : " not", + !pair.getLeft() ? "Aligned" : "", + devicePath.getFullPath()))); } } else { failedCreationSet.add(subStatus);
