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 <[email protected]>
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

Reply via email to