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 2024/02/23 08:26:18 UTC

(iotdb) 01/01: [IOTDB-6300] Support place time column at any column index in insert statement

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

jackietien pushed a commit to branch ty/insertTime
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 8b7da66fe20d94ad8356638c8330ce9d80d98686
Author: JackieTien97 <ja...@gmail.com>
AuthorDate: Fri Feb 23 16:26:04 2024 +0800

    [IOTDB-6300] Support place time column at any column index in insert statement
---
 .../org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4   |  18 ++--
 .../db/queryengine/plan/parser/ASTVisitor.java     | 101 ++++++++++++---------
 2 files changed, 68 insertions(+), 51 deletions(-)

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 d64bbd4d1d6..1a3d09e4f47 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
@@ -806,21 +806,21 @@ insertStatement
     ;
 
 insertColumnsSpec
-    : LR_BRACKET (TIMESTAMP|TIME)? (COMMA? nodeNameWithoutWildcard)+ RR_BRACKET
+    : LR_BRACKET insertColumn (COMMA insertColumn)* RR_BRACKET
     ;
 
-insertValuesSpec
-    : (COMMA? insertMultiValue)*
+insertColumn
+    : identifier
+    | TIME
+    | TIMESTAMP
     ;
 
-insertMultiValue
-    : LR_BRACKET timeValue (COMMA measurementValue)+ RR_BRACKET
-    | LR_BRACKET (measurementValue COMMA?)+ RR_BRACKET
+insertValuesSpec
+    : row (COMMA row)*
     ;
 
-measurementValue
-    : constant
-    | LR_BRACKET constant (COMMA constant)+ RR_BRACKET
+row
+    : LR_BRACKET constant (COMMA constant)* RR_BRACKET
     ;
 
 // Delete Statement
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 3b93613c294..7032653df8e 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
@@ -1802,78 +1802,95 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
   public Statement visitInsertStatement(IoTDBSqlParser.InsertStatementContext ctx) {
     InsertStatement insertStatement = new InsertStatement();
     insertStatement.setDevice(parsePrefixPath(ctx.prefixPath()));
-    boolean isTimeDefault = parseInsertColumnSpec(ctx.insertColumnsSpec(), insertStatement);
-    parseInsertValuesSpec(ctx.insertValuesSpec(), insertStatement, isTimeDefault);
+    int timeIndex = parseInsertColumnSpec(ctx.insertColumnsSpec(), insertStatement);
+    parseInsertValuesSpec(ctx.insertValuesSpec(), insertStatement, timeIndex);
     insertStatement.setAligned(ctx.ALIGNED() != null);
     return insertStatement;
   }
 
-  private boolean parseInsertColumnSpec(
+  private int parseInsertColumnSpec(
       IoTDBSqlParser.InsertColumnsSpecContext ctx, InsertStatement insertStatement) {
     List<String> measurementList = new ArrayList<>();
-    for (IoTDBSqlParser.NodeNameWithoutWildcardContext measurementName :
-        ctx.nodeNameWithoutWildcard()) {
-      measurementList.add(parseNodeNameWithoutWildCard(measurementName));
+    int timeIndex = -1;
+
+    for (int i = 0, size = ctx.insertColumn().size(); i < size; i++) {
+      String measurement = parseInsertColumn(ctx.insertColumn(i));
+      if ("time".equalsIgnoreCase(measurement) || "timestamp".equalsIgnoreCase(measurement)) {
+        if (timeIndex != -1) {
+          throw new SemanticException("One row should only have one time value");
+        } else {
+          timeIndex = i;
+        }
+      } else {
+        measurementList.add(measurement);
+      }
     }
     insertStatement.setMeasurementList(measurementList.toArray(new String[0]));
-    return (ctx.TIME() == null && ctx.TIMESTAMP() == null);
+    return timeIndex;
+  }
+
+  private String parseInsertColumn(IoTDBSqlParser.InsertColumnContext columnContext) {
+    return parseNodeString(columnContext.getText());
   }
 
   private void parseInsertValuesSpec(
-      IoTDBSqlParser.InsertValuesSpecContext ctx,
-      InsertStatement insertStatement,
-      boolean isTimeDefault) {
-    List<IoTDBSqlParser.InsertMultiValueContext> insertMultiValues = ctx.insertMultiValue();
+      IoTDBSqlParser.InsertValuesSpecContext ctx, InsertStatement insertStatement, int timeIndex) {
+    List<IoTDBSqlParser.RowContext> rows = ctx.row();
+    if (timeIndex == -1 && rows.size() != 1) {
+      throw new SemanticException("need timestamps when insert multi rows");
+    }
     List<String[]> valuesList = new ArrayList<>();
-    long[] timeArray = new long[insertMultiValues.size()];
-    for (int i = 0; i < insertMultiValues.size(); i++) {
+    long[] timeArray = new long[rows.size()];
+    for (int i = 0, size = rows.size(); i < size; i++) {
+      IoTDBSqlParser.RowContext row = rows.get(i);
       // parse timestamp
       long timestamp;
       List<String> valueList = new ArrayList<>();
-
-      if (insertMultiValues.get(i).timeValue() != null) {
-        if (isTimeDefault) {
-          if (insertMultiValues.size() != 1) {
-            throw new SemanticException("need timestamps when insert multi rows");
-          }
-          valueList.add(insertMultiValues.get(i).timeValue().getText());
-          timestamp = CommonDateTimeUtils.currentTime();
-        } else {
-          timestamp =
-              parseTimeValue(
-                  insertMultiValues.get(i).timeValue(), CommonDateTimeUtils.currentTime());
-          TimestampPrecisionUtils.checkTimestampPrecision(timestamp);
-        }
+      // using now() instead
+      if (timeIndex == -1) {
+        timestamp = CommonDateTimeUtils.currentTime();
       } else {
-        if (!isTimeDefault) {
-          throw new SemanticException(
-              "the measurementList's size is not consistent with the valueList's size");
-        }
-        if (insertMultiValues.size() != 1) {
-          throw new SemanticException("need timestamps when insert multi rows");
-        }
-        timestamp = parseDateFormat(SqlConstant.NOW_FUNC);
+        timestamp = parseTimeValue(row.constant(timeIndex));
+        TimestampPrecisionUtils.checkTimestampPrecision(timestamp);
       }
       timeArray[i] = timestamp;
 
       // parse values
-      List<IoTDBSqlParser.MeasurementValueContext> values =
-          insertMultiValues.get(i).measurementValue();
-      for (IoTDBSqlParser.MeasurementValueContext value : values) {
-        for (IoTDBSqlParser.ConstantContext constant : value.constant()) {
-          if (constant.STRING_LITERAL() != null) {
-            valueList.add(parseStringLiteralInInsertValue(constant.getText()));
+      List<ConstantContext> values = row.constant();
+      for (int j = 0, columnCount = values.size(); j < columnCount; j++) {
+        if (j != timeIndex) {
+          if (values.get(j).STRING_LITERAL() != null) {
+            valueList.add(parseStringLiteralInInsertValue(values.get(j).getText()));
           } else {
-            valueList.add(constant.getText());
+            valueList.add(values.get(j).getText());
           }
         }
       }
+
       valuesList.add(valueList.toArray(new String[0]));
     }
     insertStatement.setTimes(timeArray);
     insertStatement.setValuesList(valuesList);
   }
 
+  private long parseTimeValue(ConstantContext constant) {
+    if (constant.INTEGER_LITERAL() != null) {
+      try {
+        if (constant.MINUS() != null) {
+          return -Long.parseLong(constant.INTEGER_LITERAL().getText());
+        }
+        return Long.parseLong(constant.INTEGER_LITERAL().getText());
+      } catch (NumberFormatException e) {
+        throw new SemanticException(
+            String.format("Can not parse %s to long value", constant.INTEGER_LITERAL().getText()));
+      }
+    } else if (constant.dateExpression() != null) {
+      return parseDateExpression(constant.dateExpression(), CommonDateTimeUtils.currentTime());
+    } else {
+      throw new SemanticException(String.format("Can not parse %s to time", constant));
+    }
+  }
+
   // Load File
 
   @Override