diff --git a/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java b/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java index 0e9e8158ac7b..18d7795940c5 100644 --- a/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java +++ b/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java @@ -3677,6 +3677,8 @@ private DataNodeQueryMessages() {} public static final String EXCEPTION_UDFNAME_IS_NULL_83E9039B = "udfName is null"; public static final String EXCEPTION_URISTRING_IS_NULL_E7458C6A = "uriString is null"; public static final String EXCEPTION_FILEPATH_IS_NULL_84CE8A66 = "filePath is null"; + public static final String EXCEPTION_LOAD_TSFILE_PATH_CANNOT_BE_EMPTY_2B106181 = + "The LOAD TSFILE path cannot be empty."; public static final String EXCEPTION_DETAILS_IS_NULL_8EDEEA03 = "details is null"; public static final String EXCEPTION_COLUMNCATEGORY_IS_NULL_0075924B = "columnCategory is null"; public static final String EXCEPTION_ARGUMENTNAME_IS_NULL_7F8F665F = "argumentName is null"; diff --git a/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java b/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java index 1ab922fa121c..0864c4adbc9b 100644 --- a/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java +++ b/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java @@ -4420,6 +4420,8 @@ private DataNodeQueryMessages() {} public static final String EXCEPTION_UDFNAME_IS_NULL_83E9039B = "udfName 不能为空"; public static final String EXCEPTION_URISTRING_IS_NULL_E7458C6A = "uriString 不能为空"; public static final String EXCEPTION_FILEPATH_IS_NULL_84CE8A66 = "filePath 不能为空"; + public static final String EXCEPTION_LOAD_TSFILE_PATH_CANNOT_BE_EMPTY_2B106181 = + "LOAD TSFILE 路径不能为空。"; public static final String EXCEPTION_DETAILS_IS_NULL_8EDEEA03 = "details 不能为空"; public static final String EXCEPTION_COLUMNCATEGORY_IS_NULL_0075924B = "columnCategory 不能为空"; public static final String EXCEPTION_ARGUMENTNAME_IS_NULL_7F8F665F = "argumentName 不能为空"; diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/LoadTsFile.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/LoadTsFile.java index 8e46f7cd72a1..2e9adadb5766 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/LoadTsFile.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/LoadTsFile.java @@ -111,6 +111,7 @@ private LoadTsFile( initAttributes(); try { + LoadTsFileStatement.validateLoadTsFilePath(filePath); this.tsFiles = validateInternalDataDir ? LoadTsFileStatement.processTsFile(new File(filePath), validateSourcePath) diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/LoadTsFileStatement.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/LoadTsFileStatement.java index 0b0dea763112..ca0a0a3e2bf6 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/LoadTsFileStatement.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/LoadTsFileStatement.java @@ -94,6 +94,7 @@ public static LoadTsFileStatement createForPipe(String filePath) throws FileNotF private LoadTsFileStatement( String filePath, boolean validateSourcePath, boolean validateInternalDataDir) throws FileNotFoundException { + validateLoadTsFilePath(filePath); this.file = new File(filePath).getAbsoluteFile(); this.databaseLevel = IoTDBDescriptor.getInstance().getConfig().getDefaultDatabaseLevel(); this.verifySchema = true; @@ -111,6 +112,13 @@ private LoadTsFileStatement( this.statementType = StatementType.MULTI_BATCH_INSERT; } + public static void validateLoadTsFilePath(final String filePath) throws FileNotFoundException { + if (filePath == null || filePath.isEmpty()) { + throw new FileNotFoundException( + DataNodeQueryMessages.EXCEPTION_LOAD_TSFILE_PATH_CANNOT_BE_EMPTY_2B106181); + } + } + public static List processTsFile(final File file) throws FileNotFoundException { return processTsFile(file, true, true); } diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/analyze/load/LoadTsFileAnalyzerTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/analyze/load/LoadTsFileAnalyzerTest.java index 68503f3d794d..bf248d7a600b 100644 --- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/analyze/load/LoadTsFileAnalyzerTest.java +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/analyze/load/LoadTsFileAnalyzerTest.java @@ -120,6 +120,16 @@ public void testAnalyzeSingleTableFileShouldNotCountTimestampInPointCount() thro Assert.assertEquals(2, schemaCache.getVerifiedDeviceCount()); } + @Test + public void testTableLoadEmptyPathIsRejected() { + try { + new LoadTsFile(null, "", Collections.emptyMap()); + Assert.fail("Expected empty LOAD TSFILE path to be rejected."); + } catch (final RuntimeException e) { + Assert.assertTrue(e.getMessage().contains("The LOAD TSFILE path cannot be empty.")); + } + } + @Test public void testTableSchemaCacheShouldThrowMismatchWhenVerifyingDataType() throws Exception { final LoadTsFileTableSchemaCache schemaCache = createTableSchemaCache(true); diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/statement/crud/LoadTsFileStatementTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/statement/crud/LoadTsFileStatementTest.java index fac3227f4b5e..488796865b3c 100644 --- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/statement/crud/LoadTsFileStatementTest.java +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/statement/crud/LoadTsFileStatementTest.java @@ -21,6 +21,7 @@ import org.apache.iotdb.db.conf.IoTDBConfig; import org.apache.iotdb.db.conf.IoTDBDescriptor; +import org.apache.iotdb.db.queryengine.plan.parser.StatementGenerator; import org.junit.Assert; import org.junit.Test; @@ -29,6 +30,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.time.ZoneId; import java.util.Comparator; import java.util.List; import java.util.stream.Stream; @@ -144,6 +146,16 @@ public void testLoadInternalTsFileIsRejectedWithoutLeakingPath() throws Exceptio } } + @Test + public void testTreeLoadEmptyPathIsRejected() { + try { + StatementGenerator.createStatement("LOAD TSFILE ''", ZoneId.systemDefault()); + Assert.fail("Expected empty LOAD TSFILE path to be rejected."); + } catch (final RuntimeException e) { + Assert.assertTrue(e.getMessage().contains("The LOAD TSFILE path cannot be empty.")); + } + } + @Test public void testLoadPipeReceiverTsFileOutsideDataDirIsAllowed() throws Exception { final IoTDBConfig config = IoTDBDescriptor.getInstance().getConfig();