This is an automated email from the ASF dual-hosted git repository.
jackietien pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 086445cccd9 [IOTDB-6300] Support place time column at any column index
in insert statement
086445cccd9 is described below
commit 086445cccd9d4c3fcfa8ac45f6cafcbce53a230d
Author: Jackie Tien <[email protected]>
AuthorDate: Wed Feb 28 08:38:11 2024 +0800
[IOTDB-6300] Support place time column at any column index in insert
statement
---
.../db/it/IOTDBInsertWithTimeAtAnyIndexIT.java | 99 ++++++++++++++++++++
.../iotdb/db/it/IoTDBInsertWithoutTimeIT.java | 8 +-
.../it/IoTDBSyntaxConventionStringLiteralIT.java | 8 +-
.../aggregation/IoTDBCountTimeAlignedDeviceIT.java | 2 +-
.../org/apache/iotdb/db/it/cq/IoTDBCQExecIT.java | 10 +-
.../apache/iotdb/db/it/cq/IoTDBCQExecInNsIT.java | 10 +-
.../apache/iotdb/db/it/cq/IoTDBCQExecInUsIT.java | 10 +-
.../org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 | 18 ++--
.../db/queryengine/plan/parser/ASTVisitor.java | 104 ++++++++++++---------
9 files changed, 195 insertions(+), 74 deletions(-)
diff --git
a/integration-test/src/test/java/org/apache/iotdb/db/it/IOTDBInsertWithTimeAtAnyIndexIT.java
b/integration-test/src/test/java/org/apache/iotdb/db/it/IOTDBInsertWithTimeAtAnyIndexIT.java
new file mode 100644
index 00000000000..3db755bb547
--- /dev/null
+++
b/integration-test/src/test/java/org/apache/iotdb/db/it/IOTDBInsertWithTimeAtAnyIndexIT.java
@@ -0,0 +1,99 @@
+/*
+ * 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.it;
+
+import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.it.framework.IoTDBTestRunner;
+import org.apache.iotdb.itbase.category.ClusterIT;
+import org.apache.iotdb.itbase.category.LocalStandaloneIT;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+public class IOTDBInsertWithTimeAtAnyIndexIT {
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+
EnvFactory.getEnv().getConfig().getCommonConfig().setAutoCreateSchemaEnabled(true);
+ EnvFactory.getEnv().initClusterEnvironment();
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ @Test
+ public void testInsertTimeAtAnyIndex() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.addBatch("insert into root.db.d1(s1, s2, time) aligned values
(2, 3, 1)");
+ statement.addBatch("insert into root.db.d1(s1, time, s2) aligned values
(20, 10, 30)");
+ statement.addBatch("insert into root.db.d1(`time`, s1, s2) aligned
values (100, 200, 300)");
+ statement.executeBatch();
+
+ try (ResultSet resultSet = statement.executeQuery("select s1 from
root.db.d1")) {
+ assertTrue(resultSet.next());
+ assertEquals(1, resultSet.getLong(1));
+ assertEquals(2, resultSet.getFloat(2), 0.00001);
+ assertTrue(resultSet.next());
+ assertEquals(10, resultSet.getLong(1));
+ assertEquals(20, resultSet.getFloat(2), 0.00001);
+ assertTrue(resultSet.next());
+ assertEquals(100, resultSet.getLong(1));
+ assertEquals(200, resultSet.getFloat(2), 0.00001);
+ assertFalse(resultSet.next());
+ }
+ }
+ }
+
+ @Test
+ public void testInsertMultiTime() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ try {
+ statement.addBatch(
+ "insert into root.db.d1(s1, s2, time, time) aligned values (2, 3,
1, 1)");
+ statement.executeBatch();
+ fail();
+ } catch (SQLException e) {
+ // expected
+ }
+
+ } catch (SQLException e) {
+ fail();
+ }
+ }
+}
diff --git
a/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBInsertWithoutTimeIT.java
b/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBInsertWithoutTimeIT.java
index d9d576ea20a..62d04de083a 100644
---
a/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBInsertWithoutTimeIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBInsertWithoutTimeIT.java
@@ -101,7 +101,8 @@ public class IoTDBInsertWithoutTimeIT {
@Test
public void testInsertWithoutValueColumns() {
assertNonQueryTestFail(
- "insert into root.sg1.d1(time) values (1)", "Error occurred while
parsing SQL");
+ "insert into root.sg1.d1(time) values (1)",
+ "InsertStatement should contain at least one measurement");
}
@Test
@@ -117,9 +118,10 @@ public class IoTDBInsertWithoutTimeIT {
@Test
public void testInsertWithMultiTimesColumns() {
assertNonQueryTestFail(
- "insert into root.sg1.d1(time, time) values (1, 1)", "Error occurred
while parsing SQL");
+ "insert into root.sg1.d1(time, time) values (1, 1)",
+ "One row should only have one time value");
assertNonQueryTestFail(
"insert into root.sg1.d1(time, s1, time) values (1, 1, 1)",
- "Error occurred while parsing SQL");
+ "One row should only have one time value");
}
}
diff --git
a/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBSyntaxConventionStringLiteralIT.java
b/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBSyntaxConventionStringLiteralIT.java
index ceadf96ab3e..27a88f44736 100644
---
a/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBSyntaxConventionStringLiteralIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBSyntaxConventionStringLiteralIT.java
@@ -179,7 +179,7 @@ public class IoTDBSyntaxConventionStringLiteralIT {
String errorMsg =
TSStatusCode.SQL_PARSE_ERROR.getStatusCode()
+ ": Error occurred while parsing SQL to physical plan: "
- + "line 1:45 no viable alternative at input '(1, string'";
+ + "line 1:45 mismatched input 'string' expecting {FALSE, NAN, NOW,
NULL, TRUE, '-', '+', '/', '.', STRING_LITERAL, DATETIME_LITERAL,
INTEGER_LITERAL, EXPONENT_NUM_PART}";
try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {
statement.execute("CREATE TIMESERIES root.sg1.d1.s1 TEXT");
@@ -198,7 +198,7 @@ public class IoTDBSyntaxConventionStringLiteralIT {
String errorMsg1 =
TSStatusCode.SQL_PARSE_ERROR.getStatusCode()
+ ": Error occurred while parsing SQL to physical plan: "
- + "line 1:45 no viable alternative at input '(1, `string`'";
+ + "line 1:45 mismatched input '`string`' expecting {FALSE, NAN,
NOW, NULL, TRUE, '-', '+', '/', '.', STRING_LITERAL, DATETIME_LITERAL,
INTEGER_LITERAL, EXPONENT_NUM_PART}";
try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {
// wrap STRING_LITERAL with ``
@@ -211,7 +211,7 @@ public class IoTDBSyntaxConventionStringLiteralIT {
String errorMsg2 =
TSStatusCode.SQL_PARSE_ERROR.getStatusCode()
+ ": Error occurred while parsing SQL to physical plan: "
- + "line 1:53 token recognition error at: '')'";
+ + "line 1:47 extraneous input 'string' expecting {',', ')'}";
try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {
// single ' in ''
@@ -224,7 +224,7 @@ public class IoTDBSyntaxConventionStringLiteralIT {
String errorMsg3 =
TSStatusCode.SQL_PARSE_ERROR.getStatusCode()
+ ": Error occurred while parsing SQL to physical plan: "
- + "line 1:53 token recognition error at: '\")'";
+ + "line 1:47 extraneous input 'string' expecting {',', ')'}";
try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {
// single " in ""
diff --git
a/integration-test/src/test/java/org/apache/iotdb/db/it/aggregation/IoTDBCountTimeAlignedDeviceIT.java
b/integration-test/src/test/java/org/apache/iotdb/db/it/aggregation/IoTDBCountTimeAlignedDeviceIT.java
index d1647cd3ef5..621a3867a26 100644
---
a/integration-test/src/test/java/org/apache/iotdb/db/it/aggregation/IoTDBCountTimeAlignedDeviceIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/db/it/aggregation/IoTDBCountTimeAlignedDeviceIT.java
@@ -50,7 +50,7 @@ public class IoTDBCountTimeAlignedDeviceIT {
"CREATE ALIGNED TIMESERIES root.aligned.downsampling.d2(s1 INT32, s2
INT32);",
"INSERT INTO root.aligned.downsampling.d1(time, s1, s2) ALIGNED
VALUES(0, 0, null), (1, null, 1), "
+ "(2, null, 2), (4,4,null), (5,5,5), (7,null,7), (8,8,8),
(9,null,9);",
- "INSERT INTO root.aligned.downsampling.d2(time, s1, s2) ALIGNED
VALUES(0,null,0) (1, 1, null), (2,2,null), "
+ "INSERT INTO root.aligned.downsampling.d2(time, s1, s2) ALIGNED
VALUES(0,null,0), (1, 1, null), (2,2,null), "
+ "(4,null,4), (5,5,5), (7,7,null), (8,8,8);",
// test group by variation
diff --git
a/integration-test/src/test/java/org/apache/iotdb/db/it/cq/IoTDBCQExecIT.java
b/integration-test/src/test/java/org/apache/iotdb/db/it/cq/IoTDBCQExecIT.java
index c83510beacf..ea00bbfa646 100644
---
a/integration-test/src/test/java/org/apache/iotdb/db/it/cq/IoTDBCQExecIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/db/it/cq/IoTDBCQExecIT.java
@@ -55,7 +55,7 @@ public class IoTDBCQExecIT {
@Test
public void testCQExecution1() {
String insertTemplate =
- "INSERT INTO root.sg.d1(time, s1) VALUES (%d, %d) (%d, %d) (%d, %d)
(%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d)";
+ "INSERT INTO root.sg.d1(time, s1) VALUES (%d, %d), (%d, %d), (%d, %d),
(%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d)";
try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {
long now = System.currentTimeMillis();
@@ -142,7 +142,7 @@ public class IoTDBCQExecIT {
@Test
public void testCQExecution2() {
String insertTemplate =
- "INSERT INTO root.sg.d2(time, s1) VALUES (%d, %d) (%d, %d) (%d, %d)
(%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d)";
+ "INSERT INTO root.sg.d2(time, s1) VALUES (%d, %d), (%d, %d), (%d, %d),
(%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d)";
try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {
long now = System.currentTimeMillis();
@@ -230,7 +230,7 @@ public class IoTDBCQExecIT {
@Test
public void testCQExecution3() {
String insertTemplate =
- "INSERT INTO root.sg.d3(time, s1) VALUES (%d, %d) (%d, %d) (%d, %d)
(%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d)";
+ "INSERT INTO root.sg.d3(time, s1) VALUES (%d, %d), (%d, %d), (%d, %d),
(%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d)";
try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {
long now = System.currentTimeMillis();
@@ -329,7 +329,7 @@ public class IoTDBCQExecIT {
@Test
public void testCQExecution4() {
String insertTemplate =
- "INSERT INTO root.sg.d4(time, s1) VALUES (%d, %d) (%d, %d) (%d, %d)
(%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d)";
+ "INSERT INTO root.sg.d4(time, s1) VALUES (%d, %d), (%d, %d), (%d, %d),
(%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d)";
try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {
long now = System.currentTimeMillis();
@@ -415,7 +415,7 @@ public class IoTDBCQExecIT {
@Test
public void testCQExecution5() {
String insertTemplate =
- "INSERT INTO root.sg.d5(time, s1) VALUES (%d, %d) (%d, %d) (%d, %d)
(%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d)";
+ "INSERT INTO root.sg.d5(time, s1) VALUES (%d, %d), (%d, %d), (%d, %d),
(%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d)";
try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {
long now = System.currentTimeMillis();
diff --git
a/integration-test/src/test/java/org/apache/iotdb/db/it/cq/IoTDBCQExecInNsIT.java
b/integration-test/src/test/java/org/apache/iotdb/db/it/cq/IoTDBCQExecInNsIT.java
index 453cd73cbd7..80acdb14087 100644
---
a/integration-test/src/test/java/org/apache/iotdb/db/it/cq/IoTDBCQExecInNsIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/db/it/cq/IoTDBCQExecInNsIT.java
@@ -57,7 +57,7 @@ public class IoTDBCQExecInNsIT {
@Test
public void testCQExecution1() {
String insertTemplate =
- "INSERT INTO root.sg.d1(time, s1) VALUES (%d, %d) (%d, %d) (%d, %d)
(%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d)";
+ "INSERT INTO root.sg.d1(time, s1) VALUES (%d, %d), (%d, %d), (%d, %d),
(%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d)";
try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {
long now = System.currentTimeMillis() * 1_000_000L;
@@ -147,7 +147,7 @@ public class IoTDBCQExecInNsIT {
@Test
public void testCQExecution2() {
String insertTemplate =
- "INSERT INTO root.sg.d2(time, s1) VALUES (%d, %d) (%d, %d) (%d, %d)
(%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d)";
+ "INSERT INTO root.sg.d2(time, s1) VALUES (%d, %d), (%d, %d), (%d, %d),
(%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d)";
try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {
long now = System.currentTimeMillis() * 1_000_000L;
@@ -239,7 +239,7 @@ public class IoTDBCQExecInNsIT {
@Test
public void testCQExecution3() {
String insertTemplate =
- "INSERT INTO root.sg.d3(time, s1) VALUES (%d, %d) (%d, %d) (%d, %d)
(%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d)";
+ "INSERT INTO root.sg.d3(time, s1) VALUES (%d, %d), (%d, %d), (%d, %d),
(%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d)";
try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {
long now = System.currentTimeMillis() * 1_000_000L;
@@ -338,7 +338,7 @@ public class IoTDBCQExecInNsIT {
@Test
public void testCQExecution4() {
String insertTemplate =
- "INSERT INTO root.sg.d4(time, s1) VALUES (%d, %d) (%d, %d) (%d, %d)
(%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d)";
+ "INSERT INTO root.sg.d4(time, s1) VALUES (%d, %d), (%d, %d), (%d, %d),
(%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d)";
try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {
long now = System.currentTimeMillis() * 1_000_000L;
@@ -424,7 +424,7 @@ public class IoTDBCQExecInNsIT {
@Test
public void testCQExecution5() {
String insertTemplate =
- "INSERT INTO root.sg.d5(time, s1) VALUES (%d, %d) (%d, %d) (%d, %d)
(%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d)";
+ "INSERT INTO root.sg.d5(time, s1) VALUES (%d, %d), (%d, %d), (%d, %d),
(%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d)";
try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {
long now = System.currentTimeMillis() * 1_000_000L;
diff --git
a/integration-test/src/test/java/org/apache/iotdb/db/it/cq/IoTDBCQExecInUsIT.java
b/integration-test/src/test/java/org/apache/iotdb/db/it/cq/IoTDBCQExecInUsIT.java
index 14a03e7e66f..c9971af3afb 100644
---
a/integration-test/src/test/java/org/apache/iotdb/db/it/cq/IoTDBCQExecInUsIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/db/it/cq/IoTDBCQExecInUsIT.java
@@ -57,7 +57,7 @@ public class IoTDBCQExecInUsIT {
@Test
public void testCQExecution1() {
String insertTemplate =
- "INSERT INTO root.sg.d1(time, s1) VALUES (%d, %d) (%d, %d) (%d, %d)
(%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d)";
+ "INSERT INTO root.sg.d1(time, s1) VALUES (%d, %d), (%d, %d), (%d, %d),
(%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d)";
try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {
long now = System.currentTimeMillis() * 1_000L;
@@ -147,7 +147,7 @@ public class IoTDBCQExecInUsIT {
@Test
public void testCQExecution2() {
String insertTemplate =
- "INSERT INTO root.sg.d2(time, s1) VALUES (%d, %d) (%d, %d) (%d, %d)
(%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d)";
+ "INSERT INTO root.sg.d2(time, s1) VALUES (%d, %d), (%d, %d), (%d, %d),
(%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d)";
try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {
long now = System.currentTimeMillis() * 1_000L;
@@ -239,7 +239,7 @@ public class IoTDBCQExecInUsIT {
@Test
public void testCQExecution3() {
String insertTemplate =
- "INSERT INTO root.sg.d3(time, s1) VALUES (%d, %d) (%d, %d) (%d, %d)
(%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d)";
+ "INSERT INTO root.sg.d3(time, s1) VALUES (%d, %d), (%d, %d), (%d, %d),
(%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d)";
try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {
long now = System.currentTimeMillis() * 1_000L;
@@ -338,7 +338,7 @@ public class IoTDBCQExecInUsIT {
@Test
public void testCQExecution4() {
String insertTemplate =
- "INSERT INTO root.sg.d4(time, s1) VALUES (%d, %d) (%d, %d) (%d, %d)
(%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d)";
+ "INSERT INTO root.sg.d4(time, s1) VALUES (%d, %d), (%d, %d), (%d, %d),
(%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d)";
try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {
long now = System.currentTimeMillis() * 1_000L;
@@ -424,7 +424,7 @@ public class IoTDBCQExecInUsIT {
@Test
public void testCQExecution5() {
String insertTemplate =
- "INSERT INTO root.sg.d5(time, s1) VALUES (%d, %d) (%d, %d) (%d, %d)
(%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d) (%d, %d)";
+ "INSERT INTO root.sg.d5(time, s1) VALUES (%d, %d), (%d, %d), (%d, %d),
(%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d), (%d, %d)";
try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {
long now = System.currentTimeMillis() * 1_000L;
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..65d59d5239c 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,98 @@ 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);
+ }
+ }
+ if (measurementList.isEmpty()) {
+ throw new SemanticException("InsertStatement should contain at least one
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