This is an automated email from the ASF dual-hosted git repository.

rong pushed a commit to branch rc/1.3.3
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/rc/1.3.3 by this push:
     new 3a5304a78da Load: New SQL grammer -> LOAD <filePath> with ('k'='v', 
...) (#13553)
3a5304a78da is described below

commit 3a5304a78daba9f47e5bbecbc957554b45ba00ed
Author: YC27 <[email protected]>
AuthorDate: Fri Sep 20 13:21:01 2024 +0800

    Load: New SQL grammer -> LOAD <filePath> with ('k'='v', ...) (#13553)
    
    Co-authored-by: Steve Yurong Su <[email protected]>
    (cherry picked from commit 3f922e72c59ea869868067ac52912fc0e80bb718)
---
 .../org/apache/iotdb/db/it/IoTDBLoadTsFileIT.java  |   8 +-
 .../org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4   |  13 ++-
 .../db/queryengine/plan/parser/ASTVisitor.java     |  22 ++++-
 .../plan/statement/crud/LoadTsFileStatement.java   |  18 ++++
 .../load/config/LoadTsFileConfigurator.java        | 100 +++++++++++++++++++++
 5 files changed, 157 insertions(+), 4 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 ca5aca30b8d..11892f32921 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
@@ -542,7 +542,9 @@ public class IoTDBLoadTsFileIT {
         final Statement statement = connection.createStatement()) {
 
       statement.execute(
-          String.format("load \"%s\" sglevel=2 onSuccess=none", 
file1.getAbsolutePath()));
+          String.format(
+              "load \"%s\" with ('database-level'='2', 'on-success'='none')",
+              file1.getAbsolutePath()));
 
       try (final ResultSet resultSet =
           statement.executeQuery("select count(*) from root.** group by 
level=1,2")) {
@@ -560,7 +562,9 @@ public class IoTDBLoadTsFileIT {
         final Statement statement = connection.createStatement()) {
 
       statement.execute(
-          String.format("load \"%s\" sglevel=2 onSuccess=delete", 
file2.getAbsolutePath()));
+          String.format(
+              "load \"%s\" with ('database-level'='2', 'on-success'='delete')",
+              file2.getAbsolutePath()));
 
       try (final ResultSet resultSet =
           statement.executeQuery("select count(*) from root.** group by 
level=1,2")) {
diff --git 
a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 
b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
index 1d45ccb3d36..d742d79ac8d 100644
--- 
a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
+++ 
b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
@@ -1128,7 +1128,7 @@ loadTimeseries
 
 // Load TsFile
 loadFile
-    : LOAD fileName=STRING_LITERAL loadFileAttributeClauses?
+    : LOAD fileName=STRING_LITERAL ((loadFileAttributeClauses?) | 
(loadFileWithAttributeClauses))
     ;
 
 loadFileAttributeClauses
@@ -1141,6 +1141,17 @@ loadFileAttributeClause
     | ONSUCCESS operator_eq (DELETE|NONE)
     ;
 
+loadFileWithAttributeClauses
+    : WITH
+        LR_BRACKET
+        (loadFileWithAttributeClause COMMA)* loadFileWithAttributeClause?
+        RR_BRACKET
+    ;
+
+loadFileWithAttributeClause
+    : loadFileWithKey=STRING_LITERAL OPERATOR_SEQ 
loadFileWithValue=STRING_LITERAL
+    ;
+
 // Remove TsFile
 removeFile
     : REMOVE fileName=STRING_LITERAL
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
index 099678ffcee..af3453c1e73 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
@@ -216,6 +216,7 @@ import 
org.apache.iotdb.db.queryengine.plan.statement.sys.quota.SetThrottleQuota
 import 
org.apache.iotdb.db.queryengine.plan.statement.sys.quota.ShowSpaceQuotaStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.sys.quota.ShowThrottleQuotaStatement;
 import org.apache.iotdb.db.schemaengine.template.TemplateAlterOperationType;
+import org.apache.iotdb.db.storageengine.load.config.LoadTsFileConfigurator;
 import org.apache.iotdb.db.utils.DateTimeUtils;
 import org.apache.iotdb.db.utils.TimestampPrecisionUtils;
 import org.apache.iotdb.db.utils.constant.SqlConstant;
@@ -2003,8 +2004,27 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
   @Override
   public Statement visitLoadFile(IoTDBSqlParser.LoadFileContext ctx) {
     try {
-      LoadTsFileStatement loadTsFileStatement =
+      final LoadTsFileStatement loadTsFileStatement =
           new LoadTsFileStatement(parseStringLiteral(ctx.fileName.getText()));
+
+      // if sql have with, return new load sql statement
+      if (ctx.loadFileWithAttributeClauses() != null) {
+        final Map<String, String> loadTsFileAttributes = new HashMap<>();
+        for (IoTDBSqlParser.LoadFileWithAttributeClauseContext 
attributeContext :
+            ctx.loadFileWithAttributeClauses().loadFileWithAttributeClause()) {
+          final String key =
+              
parseStringLiteral(attributeContext.loadFileWithKey.getText()).trim().toLowerCase();
+          final String value =
+              
parseStringLiteral(attributeContext.loadFileWithValue.getText()).trim().toLowerCase();
+
+          LoadTsFileConfigurator.validateParameters(key, value);
+          loadTsFileAttributes.put(key, value);
+        }
+
+        loadTsFileStatement.setLoadAttributes(loadTsFileAttributes);
+        return loadTsFileStatement;
+      }
+
       if (ctx.loadFileAttributeClauses() != null) {
         for (IoTDBSqlParser.LoadFileAttributeClauseContext attributeContext :
             ctx.loadFileAttributeClauses().loadFileAttributeClause()) {
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 06fa870aee6..1fb3e5f1b92 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
@@ -26,6 +26,7 @@ import 
org.apache.iotdb.db.queryengine.plan.statement.Statement;
 import org.apache.iotdb.db.queryengine.plan.statement.StatementType;
 import org.apache.iotdb.db.queryengine.plan.statement.StatementVisitor;
 import org.apache.iotdb.db.storageengine.dataregion.tsfile.TsFileResource;
+import org.apache.iotdb.db.storageengine.load.config.LoadTsFileConfigurator;
 import org.apache.iotdb.rpc.TSStatusCode;
 
 import org.apache.tsfile.common.constant.TsFileConstant;
@@ -36,6 +37,7 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 
 public class LoadTsFileStatement extends Statement {
 
@@ -45,6 +47,8 @@ public class LoadTsFileStatement extends Statement {
   private boolean deleteAfterLoad;
   private boolean autoCreateDatabase;
 
+  private Map<String, String> loadAttributes;
+
   private final List<File> tsFiles;
   private final List<TsFileResource> resources;
   private final List<Long> writePointCountList;
@@ -60,6 +64,10 @@ public class LoadTsFileStatement extends Statement {
     this.writePointCountList = new ArrayList<>();
     this.statementType = StatementType.MULTI_BATCH_INSERT;
 
+    processTsFile(filePath);
+  }
+
+  private void processTsFile(final String filePath) throws 
FileNotFoundException {
     if (file.isFile()) {
       tsFiles.add(file);
     } else {
@@ -165,6 +173,16 @@ public class LoadTsFileStatement extends Statement {
     return writePointCountList.get(resourceIndex);
   }
 
+  public void setLoadAttributes(final Map<String, String> loadAttributes) {
+    this.loadAttributes = loadAttributes;
+    initAttributes();
+  }
+
+  private void initAttributes() {
+    this.databaseLevel = 
LoadTsFileConfigurator.parseOrGetDefaultDatabaseLevel(loadAttributes);
+    this.deleteAfterLoad = 
LoadTsFileConfigurator.parseOrGetDefaultOnSuccess(loadAttributes);
+  }
+
   @Override
   public List<PartialPath> getPaths() {
     return Collections.emptyList();
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/config/LoadTsFileConfigurator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/config/LoadTsFileConfigurator.java
new file mode 100644
index 00000000000..d09540133ab
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/config/LoadTsFileConfigurator.java
@@ -0,0 +1,100 @@
+/*
+ * 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.storageengine.load.config;
+
+import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import org.apache.iotdb.db.exception.sql.SemanticException;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class LoadTsFileConfigurator {
+
+  public static void validateParameters(final String key, final String value) {
+    switch (key) {
+      case DATABASE_LEVEL_KEY:
+        validateDatabaseLevelParam(value);
+        break;
+      case ON_SUCCESS_KEY:
+        validateOnSuccessParam(value);
+        break;
+      default:
+        throw new SemanticException("Invalid parameter '" + key + "' for LOAD 
TSFILE command.");
+    }
+  }
+
+  private static final String DATABASE_LEVEL_KEY = "database-level";
+  private static final int DATABASE_LEVEL_DEFAULT_VALUE =
+      IoTDBDescriptor.getInstance().getConfig().getDefaultStorageGroupLevel();
+  private static final int DATABASE_LEVEL_MIN_VALUE = 1;
+
+  public static void validateDatabaseLevelParam(final String databaseLevel) {
+    try {
+      int level = Integer.parseInt(databaseLevel);
+      if (level < DATABASE_LEVEL_MIN_VALUE) {
+        throw new SemanticException(
+            String.format(
+                "Given database level %d is less than the minimum value %d, 
please input a valid database level.",
+                level, DATABASE_LEVEL_MIN_VALUE));
+      }
+    } catch (Exception e) {
+      throw new SemanticException(
+          String.format(
+              "Given database level %s is not a valid integer, please input a 
valid database level.",
+              databaseLevel));
+    }
+  }
+
+  public static int parseOrGetDefaultDatabaseLevel(final Map<String, String> 
loadAttributes) {
+    return Integer.parseInt(
+        loadAttributes.getOrDefault(
+            DATABASE_LEVEL_KEY, String.valueOf(DATABASE_LEVEL_DEFAULT_VALUE)));
+  }
+
+  private static final String ON_SUCCESS_KEY = "on-success";
+  private static final String ON_SUCCESS_DELETE_VALUE = "delete";
+  private static final String ON_SUCCESS_NONE_VALUE = "none";
+  private static final Set<String> ON_SUCCESS_VALUE_SET =
+      Collections.unmodifiableSet(
+          new HashSet<>(Arrays.asList(ON_SUCCESS_DELETE_VALUE, 
ON_SUCCESS_NONE_VALUE)));
+
+  public static void validateOnSuccessParam(final String onSuccess) {
+    if (!ON_SUCCESS_VALUE_SET.contains(onSuccess)) {
+      throw new SemanticException(
+          String.format(
+              "Given on-success value '%s' is not supported, please input a 
valid on-success value.",
+              onSuccess));
+    }
+  }
+
+  public static boolean parseOrGetDefaultOnSuccess(final Map<String, String> 
loadAttributes) {
+    final String value = loadAttributes.get(ON_SUCCESS_KEY);
+    return StringUtils.isEmpty(value) || ON_SUCCESS_DELETE_VALUE.equals(value);
+  }
+
+  private LoadTsFileConfigurator() {
+    throw new IllegalStateException("Utility class");
+  }
+}

Reply via email to