Add relational it (#13019)
* IoTDBFloatPrecisionIT
* modify it
* modify it
* fix it
diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java b/integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java
index f9ca418..d18b669 100644
--- a/integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java
+++ b/integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java
@@ -413,11 +413,21 @@
assertNonQueryTestFail(sql, errMsg, SessionConfig.DEFAULT_USER, SessionConfig.DEFAULT_PASSWORD);
}
+ public static void assertTableNonQueryTestFail(String sql, String errMsg, String dbName) {
+ assertTableNonQueryTestFail(
+ sql, errMsg, SessionConfig.DEFAULT_USER, SessionConfig.DEFAULT_PASSWORD, dbName);
+ }
+
public static void assertNonQueryTestFail(
String sql, String errMsg, String userName, String password) {
assertNonQueryTestFail(EnvFactory.getEnv(), sql, errMsg, userName, password);
}
+ public static void assertTableNonQueryTestFail(
+ String sql, String errMsg, String userName, String password, String dbName) {
+ assertTableNonQueryTestFail(EnvFactory.getEnv(), sql, errMsg, userName, password, dbName);
+ }
+
public static void assertNonQueryTestFail(
BaseEnv env, String sql, String errMsg, String userName, String password) {
try (Connection connection = env.getConnection(userName, password);
@@ -429,6 +439,18 @@
}
}
+ public static void assertTableNonQueryTestFail(
+ BaseEnv env, String sql, String errMsg, String userName, String password, String db) {
+ try (Connection connection = env.getConnection(userName, password, BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("use " + "\"" + db + "\"");
+ statement.execute(sql);
+ fail("No exception!");
+ } catch (SQLException e) {
+ Assert.assertTrue(e.getMessage(), e.getMessage().contains(errMsg));
+ }
+ }
+
public static void assertResultSetEqual(
ResultSet actualResultSet, String expectedHeader, String[] expectedRetArray) {
assertResultSetEqual(
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IOTDBInsertWithTimeAtAnyIndexIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IOTDBInsertWithTimeAtAnyIndexIT.java
new file mode 100644
index 0000000..cfe7d8c
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IOTDBInsertWithTimeAtAnyIndexIT.java
@@ -0,0 +1,106 @@
+/*
+ * 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.relational.it.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("create database test");
+ statement.addBatch("use \"test\"");
+ statement.addBatch(
+ "create table (id1 string id, s1 int32 measurement, s2 int32 measurement)");
+ statement.addBatch("insert into db(id, s1, s2, time) ('d1', 2, 3, 1)");
+ statement.addBatch("insert into db(id, s1, time, s2) values ('d1', 20, 10, 30)");
+ statement.addBatch("insert into db(id, `time`, s1, s2) values ('d1', 100, 200, 300)");
+ statement.executeBatch();
+
+ try (ResultSet resultSet = statement.executeQuery("select time, s1 from db")) {
+ assertTrue(resultSet.next());
+ assertEquals(1, resultSet.getLong(1));
+ assertEquals(2, resultSet.getDouble(2), 0.00001);
+ assertTrue(resultSet.next());
+ assertEquals(10, resultSet.getLong(1));
+ assertEquals(20, resultSet.getDouble(2), 0.00001);
+ assertTrue(resultSet.next());
+ assertEquals(100, resultSet.getLong(1));
+ assertEquals(200, resultSet.getDouble(2), 0.00001);
+ assertFalse(resultSet.next());
+ }
+ }
+ }
+
+ @Test
+ public void testInsertMultiTime() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ try {
+ statement.addBatch("create database test");
+ statement.addBatch("use \"test\"");
+ statement.addBatch(
+ "create table (id1 string id, s1 int32 measurement, s2 int32 measurement)");
+ statement.addBatch("insert into db(id1, s1, s2, time, time) values ('d1', 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/relational/it/db/it/IoTDBEncodingIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBEncodingIT.java
new file mode 100644
index 0000000..c6bc466
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBEncodingIT.java
@@ -0,0 +1,432 @@
+/*
+ * 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.relational.it.db.it;
+
+import org.apache.iotdb.isession.ISession;
+import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.it.framework.IoTDBTestRunner;
+import org.apache.iotdb.itbase.category.LocalStandaloneIT;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+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.Statement;
+
+import static org.apache.iotdb.itbase.env.BaseEnv.TABLE_SQL_DIALECT;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class})
+@Ignore
+public class IoTDBEncodingIT {
+
+ @Before
+ public void setUp() throws Exception {
+ EnvFactory.getEnv().initClusterEnvironment();
+ try (ISession session = EnvFactory.getEnv().getSessionConnection(TABLE_SQL_DIALECT)) {
+ session.executeNonQueryStatement("CREATE DATABASE db1");
+ }
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ try (ISession session = EnvFactory.getEnv().getSessionConnection(TABLE_SQL_DIALECT)) {
+ session.executeNonQueryStatement("DROP DATABASE db1");
+ }
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ @Test
+ public void testSetTimeEncoderRegularAndValueEncoderTS_2DIFF() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(
+ "CREATE TIMESERIES root.db_0.tab0.salary WITH DATATYPE=INT64,ENCODING=TS_2DIFF");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(1,1100)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(2,1200)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(3,1300)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(4,1400)");
+
+ statement.execute("flush");
+
+ int[] result = new int[] {1100, 1200, 1300, 1400};
+ try (ResultSet resultSet = statement.executeQuery("select * from root.db_0.tab0")) {
+ int index = 0;
+ while (resultSet.next()) {
+ int salary = resultSet.getInt("root.db_0.tab0.salary");
+ assertEquals(result[index], salary);
+ index++;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ @Test
+ public void testSetTimeEncoderRegularAndValueEncoderTS_2DIFFOutofOrder() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(
+ "CREATE TIMESERIES root.db_0.tab0.salary WITH DATATYPE=INT64,ENCODING=TS_2DIFF");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(1,1200)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(2,1100)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(7,1000)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(4,2200)");
+ statement.execute("flush");
+
+ int[] result = new int[] {1200, 1100, 2200, 1000};
+ try (ResultSet resultSet = statement.executeQuery("select * from root.db_0.tab0")) {
+ int index = 0;
+ while (resultSet.next()) {
+ int salary = resultSet.getInt("root.db_0.tab0.salary");
+ assertEquals(result[index], salary);
+ index++;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ @Test
+ public void testSetTimeEncoderRegularAndValueEncoderRLE() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("CREATE TIMESERIES root.db_0.tab0.salary WITH DATATYPE=INT64,ENCODING=RLE");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(1,1100)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(2,1200)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(3,1300)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(4,1400)");
+ statement.execute("flush");
+
+ int[] result = new int[] {1100, 1200, 1300, 1400};
+ try (ResultSet resultSet = statement.executeQuery("select * from root.db_0.tab0")) {
+ int index = 0;
+ while (resultSet.next()) {
+ int salary = resultSet.getInt("root.db_0.tab0.salary");
+ assertEquals(result[index], salary);
+ index++;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ @Test
+ public void testSetTimeEncoderRegularAndValueEncoderRLEOutofOrder() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("CREATE TIMESERIES root.db_0.tab0.salary WITH DATATYPE=INT64,ENCODING=RLE");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(1,1200)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(2,1100)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(7,1000)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(4,2200)");
+ statement.execute("flush");
+
+ int[] result = new int[] {1200, 1100, 2200, 1000};
+ try (ResultSet resultSet = statement.executeQuery("select * from root.db_0.tab0")) {
+ int index = 0;
+ while (resultSet.next()) {
+ int salary = resultSet.getInt("root.db_0.tab0.salary");
+ assertEquals(result[index], salary);
+ index++;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ @Test
+ public void testSetTimeEncoderRegularAndValueEncoderGORILLA() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(
+ "CREATE TIMESERIES root.db_0.tab0.salary WITH DATATYPE=INT64,ENCODING=GORILLA");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(1,1100)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(2,1200)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(3,1300)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(4,1400)");
+ statement.execute("flush");
+
+ int[] result = new int[] {1100, 1200, 1300, 1400};
+ try (ResultSet resultSet = statement.executeQuery("select * from root.db_0.tab0")) {
+ int index = 0;
+ while (resultSet.next()) {
+ int salary = resultSet.getInt("root.db_0.tab0.salary");
+ assertEquals(result[index], salary);
+ index++;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ @Test
+ public void testSetTimeEncoderRegularAndValueEncoderGORILLAOutofOrder() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(
+ "CREATE TIMESERIES root.db_0.tab0.salary WITH DATATYPE=INT64,ENCODING=GORILLA");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(1,1200)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(2,1100)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(7,1000)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(4,2200)");
+ statement.execute("flush");
+
+ int[] result = new int[] {1200, 1100, 2200, 1000};
+ try (ResultSet resultSet = statement.executeQuery("select * from root.db_0.tab0")) {
+ int index = 0;
+ while (resultSet.next()) {
+ int salary = resultSet.getInt("root.db_0.tab0.salary");
+ assertEquals(result[index], salary);
+ index++;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ @Test
+ public void testSetTimeEncoderRegularAndValueEncoderZIGZAG() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(
+ "CREATE TIMESERIES root.db_0.tab0.salary WITH DATATYPE=INT64,ENCODING=ZIGZAG");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(1,1100)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(2,1200)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(3,1300)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(4,1400)");
+ statement.execute("flush");
+
+ int[] result = new int[] {1100, 1200, 1300, 1400};
+ try (ResultSet resultSet = statement.executeQuery("select * from root.db_0.tab0")) {
+ int index = 0;
+ while (resultSet.next()) {
+ int salary = resultSet.getInt("root.db_0.tab0.salary");
+ assertEquals(result[index], salary);
+ index++;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ @Test
+ public void testSetTimeEncoderRegularAndValueEncoderZIGZAGOutofOrder() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(
+ "CREATE TIMESERIES root.db_0.tab0.salary WITH DATATYPE=INT64,ENCODING=ZIGZAG");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(1,1200)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(2,1100)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(7,1000)");
+ statement.execute("insert into root.db_0.tab0(time,salary) values(4,2200)");
+ statement.execute("flush");
+
+ int[] result = new int[] {1200, 1100, 2200, 1000};
+ try (ResultSet resultSet = statement.executeQuery("select * from root.db_0.tab0")) {
+ int index = 0;
+ while (resultSet.next()) {
+ int salary = resultSet.getInt("root.db_0.tab0.salary");
+ assertEquals(result[index], salary);
+ index++;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ @Test
+ public void testSetTimeEncoderRegularAndValueEncoderDictionary() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(
+ "CREATE TIMESERIES root.db_0.tab0.city WITH DATATYPE=TEXT,ENCODING=DICTIONARY");
+ statement.execute("insert into root.db_0.tab0(time,city) values(1,\"Nanjing\")");
+ statement.execute("insert into root.db_0.tab0(time,city) values(2,\"Nanjing\")");
+ statement.execute("insert into root.db_0.tab0(time,city) values(3,\"Beijing\")");
+ statement.execute("insert into root.db_0.tab0(time,city) values(4,\"Shanghai\")");
+ statement.execute("flush");
+
+ String[] result = new String[] {"Nanjing", "Nanjing", "Beijing", "Shanghai"};
+ try (ResultSet resultSet = statement.executeQuery("select * from root.db_0.tab0")) {
+ int index = 0;
+ while (resultSet.next()) {
+ String city = resultSet.getString("root.db_0.tab0.city");
+ assertEquals(result[index], city);
+ index++;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ @Test
+ public void testSetTimeEncoderRegularAndValueEncoderDictionaryOutOfOrder() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(
+ "CREATE TIMESERIES root.db_0.tab0.city WITH DATATYPE=TEXT,ENCODING=DICTIONARY");
+ statement.execute("insert into root.db_0.tab0(time,city) values(1,\"Nanjing\")");
+ statement.execute("insert into root.db_0.tab0(time,city) values(2,\"Nanjing\")");
+ statement.execute("insert into root.db_0.tab0(time,city) values(4,\"Beijing\")");
+ statement.execute("insert into root.db_0.tab0(time,city) values(3,\"Shanghai\")");
+ statement.execute("flush");
+
+ String[] result = new String[] {"Nanjing", "Nanjing", "Shanghai", "Beijing"};
+ try (ResultSet resultSet = statement.executeQuery("select * from root.db_0.tab0")) {
+ int index = 0;
+ while (resultSet.next()) {
+ String city = resultSet.getString("root.db_0.tab0.city");
+ assertEquals(result[index], city);
+ index++;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ public double SNR(int[] gd, int[] x, int length) {
+ double noise_power = 0, signal_power = 0;
+ for (int i = 0; i < length; i++) {
+ noise_power += (gd[i] - x[i]) * (gd[i] - x[i]);
+ signal_power += gd[i] * gd[i];
+ }
+ if (noise_power == 0) {
+ return Double.POSITIVE_INFINITY;
+ } else {
+ return 10 * Math.log10(signal_power / noise_power);
+ }
+ }
+
+ @Test
+ public void testDoublePrecision1() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("CREATE DATABASE root.turbine1");
+ statement.execute(
+ "create timeseries root.turbine1.d1.s1 with datatype=DOUBLE, encoding=PLAIN, compression=SNAPPY");
+
+ statement.execute("insert into root.turbine1.d1(timestamp,s1) values(1,1.2345678)");
+
+ ResultSet resultSet = statement.executeQuery("select * from root.turbine1.**");
+
+ String str = "1.2345678";
+ while (resultSet.next()) {
+ assertEquals(str, resultSet.getString("root.turbine1.d1.s1"));
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ @Test
+ public void testDoublePrecision2() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("CREATE DATABASE root.turbine1");
+ statement.execute(
+ "create timeseries root.turbine1.d1.s1 with datatype=DOUBLE, encoding=RLE, compression=SNAPPY");
+
+ statement.execute("insert into root.turbine1.d1(timestamp,s1) values(1,1.2345678)");
+
+ ResultSet resultSet = statement.executeQuery("select * from root.turbine1.**");
+
+ String str = "1.23";
+ while (resultSet.next()) {
+ assertEquals(str, resultSet.getString("root.turbine1.d1.s1"));
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ @Test
+ public void testFloatPrecision1() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("CREATE DATABASE root.turbine1");
+ statement.execute(
+ "create timeseries root.turbine1.d1.s1 with datatype=FLOAT, encoding=PLAIN, compression=SNAPPY");
+
+ statement.execute("insert into root.turbine1.d1(timestamp,s1) values(1,1.2345678)");
+
+ ResultSet resultSet = statement.executeQuery("select * from root.turbine1.**");
+
+ String str = "1.2345678";
+ while (resultSet.next()) {
+ assertEquals(str, resultSet.getString("root.turbine1.d1.s1"));
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ @Test
+ public void testFloatPrecision2() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("CREATE DATABASE root.turbine1");
+ statement.execute(
+ "create timeseries root.turbine1.d1.s1 with datatype=FLOAT, encoding=RLE, compression=SNAPPY");
+
+ statement.execute("insert into root.turbine1.d1(timestamp,s1) values(1,1.2345678)");
+
+ ResultSet resultSet = statement.executeQuery("select * from root.turbine1.**");
+
+ String str = "1.23";
+ while (resultSet.next()) {
+ assertEquals(str, resultSet.getString("root.turbine1.d1.s1"));
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBExecuteBatchIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBExecuteBatchIT.java
new file mode 100644
index 0000000..2727aa3
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBExecuteBatchIT.java
@@ -0,0 +1,149 @@
+/*
+ * 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.relational.it.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.apache.iotdb.itbase.category.RemoteIT;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+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.apache.iotdb.itbase.env.BaseEnv.TABLE_SQL_DIALECT;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class, RemoteIT.class})
+@Ignore // 'Drop Table' and 'Alter table' is not supported
+public class IoTDBExecuteBatchIT {
+ @Before
+ public void setUp() throws Exception {
+ EnvFactory.getEnv().initClusterEnvironment();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ @Test
+ public void testJDBCExecuteBatch() {
+
+ try (Connection connection = EnvFactory.getEnv().getConnection(TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.setFetchSize(5);
+ statement.addBatch("create database ln");
+ statement.addBatch("USE \"ln\"");
+ statement.addBatch("create table wf01 (id1 string id, temprature double measurement)");
+ statement.addBatch(
+ "insert into wf01(id1,time,temperature) values(\'wt01\', 1509465600000,1.2)");
+ statement.addBatch(
+ "insert into wf01(id1,time,temperature) values(\'wt01\', 1509465600001,2.3)");
+
+ statement.addBatch("drop table wf01");
+ statement.addBatch("create table wf01 (id1 string id, temprature double measurement)");
+
+ statement.addBatch(
+ "insert into wf01(id1,time,temperature) values(\'wt01\', 1509465600002,3.4)");
+ statement.executeBatch();
+ statement.clearBatch();
+ ResultSet resultSet = statement.executeQuery("select * from wf01");
+ int count = 0;
+
+ String[] timestamps = {"1509465600002"};
+ String[] values = {"3.4"};
+
+ while (resultSet.next()) {
+ assertEquals(timestamps[count], resultSet.getString("time"));
+ assertEquals(values[count], resultSet.getString("temperature"));
+ count++;
+ }
+ } catch (SQLException e) {
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void testJDBCExecuteBatchForCreateMultiTimeSeriesPlan() {
+ try (Connection connection = EnvFactory.getEnv().getConnection(TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.setFetchSize(100);
+ statement.execute("create database ln");
+ statement.execute("USE \"ln\"");
+ statement.addBatch("create table wf01 (id1 string id, temprature double measurement)");
+
+ statement.addBatch(
+ "insert into wf01(id1,time,temperature) values(\'wt01\', 1509465600000,1.2)");
+ statement.addBatch(
+ "insert into wf01(id1,time,temperature) values(\'wt01\', 1509465600001,2.3)");
+ statement.addBatch("drop table wf01");
+
+ statement.addBatch(
+ "create table turbine (id1 string id, attr1 string attribute, attr2 string attribute, s1 boolean measurement, s2 float measurement)");
+
+ statement.addBatch("create table wf01 (id1 string id, temprature double measurement)");
+ statement.addBatch(
+ "insert into wf01(id1,time,temperature) values(\'wt01\', 1509465600002,3.4)");
+ statement.addBatch("alter table turbine add column s3 boolean measurement");
+ statement.executeBatch();
+ statement.clearBatch();
+ ResultSet resultSet = statement.executeQuery("select * from wf01");
+ String[] timestamps = {"1509465600002"};
+ String[] values = {"3.4"};
+ int count = 0;
+ while (resultSet.next()) {
+ assertEquals(timestamps[count], resultSet.getString("time"));
+ assertEquals(values[count], resultSet.getString("temperature"));
+ count++;
+ }
+ ResultSet timeSeriesResultSetForS1 = statement.executeQuery("describe turbine");
+ count = 0;
+ String[] keys = {"ColumnName", "DataType", "Category"};
+ String[][] value_columns = {
+ new String[] {"Time", "TIMESTAMP", "TIME"},
+ new String[] {"id1", "STRING", "ID"},
+ new String[] {"attr1", "STRING", "ATTRIBUTE"},
+ new String[] {"attr2", "STRING", "ATTRIBUTE"},
+ new String[] {"s1", "BOOLEAN", "MEASUREMENT"},
+ new String[] {"s2", "FLOAT", "MEASUREMENT"},
+ };
+
+ while (timeSeriesResultSetForS1.next()) {
+ for (int i = 0; i < keys.length; i++) {
+ assertEquals(value_columns[count][i], timeSeriesResultSetForS1.getString(keys[i]));
+ }
+ count++;
+ }
+ } catch (SQLException e) {
+ fail(e.getMessage());
+ }
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBFloatPrecisionIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBFloatPrecisionIT.java
new file mode 100644
index 0000000..3dac960
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBFloatPrecisionIT.java
@@ -0,0 +1,161 @@
+/*
+ * 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.relational.it.db.it;
+
+import org.apache.iotdb.db.utils.MathUtils;
+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.apache.iotdb.itbase.category.RemoteIT;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringJoiner;
+
+import static org.apache.iotdb.itbase.env.BaseEnv.TABLE_SQL_DIALECT;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+/**
+ * Notice that, all test begins with "IoTDB" is integration test. All test which will start the
+ * IoTDB server should be defined as integration test.
+ */
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class, RemoteIT.class})
+public class IoTDBFloatPrecisionIT {
+
+ private static final String INSERT_TEMPLATE_SQL = "insert into %s(id1,time,%s) values(%s,%d,%s)";
+ private static List<String> sqls = new ArrayList<>();
+ private static final int TIMESTAMP = 10;
+ private static final String VALUE = "1.2345678901";
+ private static final float DELTA_FLOAT = 0.0000001f;
+ private static final double DELTA_DOUBLE = 0.0000001d;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ EnvFactory.getEnv().initClusterEnvironment();
+ initCreateSQLStatement();
+
+ insertData();
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ private static void initCreateSQLStatement() {
+ sqls.add("CREATE DATABASE test");
+ StringJoiner createTableSql =
+ new StringJoiner(",", "CREATE TABLE vehicle (id1 string id, ", ")");
+ for (int i = 0; i < 10; i++) {
+ createTableSql.add("s" + i + "f" + " FLOAT measurement");
+ createTableSql.add("s" + i + "d" + " DOUBLE measurement");
+ }
+ sqls.add("USE \"test\"");
+ sqls.add(createTableSql.toString());
+ for (int i = 0; i < 10; i++) {
+ sqls.add(
+ String.format(INSERT_TEMPLATE_SQL, "vehicle", "s" + i + "f", "\'fd\'", TIMESTAMP, VALUE));
+ sqls.add(
+ String.format(INSERT_TEMPLATE_SQL, "vehicle", "s" + i + "d", "\'fd\'", TIMESTAMP, VALUE));
+ }
+ }
+
+ private static void insertData() {
+ try (Connection connection = EnvFactory.getEnv().getConnection(TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+
+ for (String sql : sqls) {
+ statement.execute(sql);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ @Ignore
+ // CREATE TIMESERIES root.vehicle.%s.%s WITH DATATYPE=%s, ENCODING=%s, 'MAX_POINT_NUMBER'='%d'
+ // Should support 'MAX_POINT_NUMBER'='%d'
+ public void selectAllSQLTest() {
+ try (Connection connection = EnvFactory.getEnv().getConnection(TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("USE \"test\"");
+ int cnt;
+ try (ResultSet resultSet = statement.executeQuery("select * from vehicle")) {
+ assertNotNull(resultSet);
+ cnt = 0;
+ while (resultSet.next()) {
+ assertEquals(TIMESTAMP, resultSet.getTimestamp("time").getTime());
+ for (int i = 0; i < 10; i++) {
+ assertEquals(
+ MathUtils.roundWithGivenPrecision(Float.parseFloat(VALUE), i),
+ resultSet.getFloat("s" + i + "f"),
+ DELTA_FLOAT);
+ assertEquals(
+ MathUtils.roundWithGivenPrecision(Double.parseDouble(VALUE), i),
+ resultSet.getDouble("s" + i + "d"),
+ DELTA_DOUBLE);
+ }
+ cnt++;
+ }
+ assertEquals(1, cnt);
+ }
+
+ statement.execute("flush");
+ try (ResultSet resultSet = statement.executeQuery("select * from vehicle")) {
+ cnt = 0;
+ while (resultSet.next()) {
+ assertEquals(TIMESTAMP, resultSet.getTimestamp("time").getTime());
+ for (int i = 0; i < 10; i++) {
+ BigDecimal b = new BigDecimal(VALUE);
+ assertEquals(
+ b.setScale(i, RoundingMode.HALF_UP).floatValue(),
+ resultSet.getFloat("s" + i + "f"),
+ DELTA_FLOAT);
+ assertEquals(
+ b.setScale(i, RoundingMode.HALF_UP).doubleValue(),
+ resultSet.getDouble("s" + i + "d"),
+ DELTA_DOUBLE);
+ }
+ cnt++;
+ }
+ assertEquals(1, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBFlushQueryIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBFlushQueryIT.java
new file mode 100644
index 0000000..42d1ce4
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBFlushQueryIT.java
@@ -0,0 +1,200 @@
+/*
+ * 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.relational.it.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.apache.iotdb.itbase.env.BaseEnv;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+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 java.util.Locale;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+public class IoTDBFlushQueryIT {
+
+ private static String[] sqls =
+ new String[] {
+ "CREATE DATABASE test",
+ "USE \"test\"",
+ "CREATE TABLE vehicle (id1 string id, s0 int32 measurement)",
+ "insert into vehicle(id1,time,s0) values('d0',1,101)",
+ "insert into vehicle(id1,time,s0) values('d0',2,198)",
+ "insert into vehicle(id1,time,s0) values('d0',100,99)",
+ "insert into vehicle(id1,time,s0) values('d0',101,99)",
+ "insert into vehicle(id1,time,s0) values('d0',102,80)",
+ "insert into vehicle(id1,time,s0) values('d0',103,99)",
+ "insert into vehicle(id1,time,s0) values('d0',104,90)",
+ "insert into vehicle(id1,time,s0) values('d0',105,99)",
+ "insert into vehicle(id1,time,s0) values('d0',106,99)",
+ "flush",
+ "insert into vehicle(id1,time,s0) values('d0',2,10000)",
+ "insert into vehicle(id1,time,s0) values('d0',50,10000)",
+ "insert into vehicle(id1,time,s0) values('d0',1000,22222)",
+ };
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ EnvFactory.getEnv().initClusterEnvironment();
+ insertData();
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ private static void insertData() {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ for (String sql : sqls) {
+ System.out.println(sql);
+ statement.execute(sql);
+ }
+ } catch (Exception e) {
+ fail("insertData failed.");
+ }
+ }
+
+ @Test
+ public void selectAllSQLTest() {
+
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("USE \"test\"");
+ try (ResultSet resultSet = statement.executeQuery("SELECT * FROM vehicle"); ) {
+ int cnt = 0;
+ while (resultSet.next()) {
+ cnt++;
+ }
+ }
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void testFlushGivenGroup() {
+ String insertTemplate =
+ "INSERT INTO vehicle(id1, time, s1, s2, s3) VALUES (%s, %d, %d, %f, %s)";
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+
+ statement.execute("CREATE DATABASE group1");
+ statement.execute("CREATE DATABASE group2");
+ statement.execute("CREATE DATABASE group3");
+
+ for (int i = 1; i <= 3; i++) {
+ statement.execute(String.format("USE \"group%d\"", i));
+ statement.execute(
+ "CREATE TABLE vehicle (id1 string id, s1 int32 measurement, s2 float measurement, s3 string measurement)");
+ for (int j = 10; j < 20; j++) {
+ statement.execute(String.format(Locale.CHINA, insertTemplate, i, j, j, j * 0.1, j));
+ }
+ }
+ statement.execute("FLUSH");
+
+ for (int i = 1; i <= 3; i++) {
+ statement.execute(String.format("USE \"group%d\"", i));
+ for (int j = 0; j < 10; j++) {
+ statement.execute(String.format(Locale.CHINA, insertTemplate, i, j, j, j * 0.1, j));
+ }
+ }
+ statement.execute("FLUSH group1");
+ statement.execute("FLUSH group2,group3");
+
+ for (int i = 1; i <= 3; i++) {
+ statement.execute(String.format("USE \"group%d\"", i));
+ for (int j = 0; j < 30; j++) {
+ statement.execute(String.format(Locale.CHINA, insertTemplate, i, j, j, j * 0.1, j));
+ }
+ }
+ statement.execute("FLUSH group1 TRUE");
+ statement.execute("FLUSH group2,group3 FALSE");
+
+ for (int i = 1; i <= 3; i++) {
+ statement.execute(String.format("USE \"group%d\"", i));
+ int count = 0;
+ try (ResultSet resultSet = statement.executeQuery("SELECT * FROM vehicle")) {
+ while (resultSet.next()) {
+ count++;
+ }
+ }
+ assertEquals(30, count);
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void testFlushGivenGroupNoData() {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("CREATE DATABASE nodatagroup1");
+ statement.execute("CREATE DATABASE nodatagroup2");
+ statement.execute("CREATE DATABASE nodatagroup3");
+ statement.execute("FLUSH nodatagroup1");
+ statement.execute("FLUSH nodatagroup2");
+ statement.execute("FLUSH nodatagroup3");
+ statement.execute("FLUSH nodatagroup1, nodatagroup2");
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ @Ignore
+ public void testFlushNotExistGroupNoData() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("CREATE DATABASE root.noexist.nodatagroup1");
+ try {
+ statement.execute(
+ "FLUSH root.noexist.nodatagroup1,root.notExistGroup1,root.notExistGroup2");
+ } catch (SQLException sqe) {
+ String expectedMsg =
+ "322: 322: storageGroup root.notExistGroup1,root.notExistGroup2 does not exist";
+ sqe.printStackTrace();
+ assertTrue(sqe.getMessage().contains(expectedMsg));
+ }
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertMultiPartitionIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertMultiPartitionIT.java
new file mode 100644
index 0000000..3d3654d
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertMultiPartitionIT.java
@@ -0,0 +1,75 @@
+/*
+ * 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.relational.it.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.apache.iotdb.itbase.category.RemoteIT;
+import org.apache.iotdb.itbase.env.BaseEnv;
+
+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.Statement;
+
+import static org.junit.Assert.fail;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class, RemoteIT.class})
+public class IoTDBInsertMultiPartitionIT {
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ EnvFactory.getEnv()
+ .getConfig()
+ .getDataNodeCommonConfig()
+ .setWriteMemoryProportion("10000000:1");
+ EnvFactory.getEnv().initClusterEnvironment();
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ @Test
+ public void testInsertMultiPartition() {
+
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("create database test");
+ statement.execute("use \"test\"");
+ statement.execute("create table sg (id1 string id, s1 int32 measurement)");
+ statement.execute("insert into sg(id1,time,s1) values('d1',1,2)");
+ statement.execute("flush");
+ statement.execute("insert into sg(id1,time,s1) values('d1',2,2)");
+ statement.execute("insert into sg(id1,time,s1) values('d1',604800001,2)");
+ statement.execute("flush");
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertMultiRowIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertMultiRowIT.java
new file mode 100644
index 0000000..2509766
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertMultiRowIT.java
@@ -0,0 +1,195 @@
+/*
+ * 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.relational.it.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.apache.iotdb.itbase.env.BaseEnv;
+import org.apache.iotdb.rpc.TSStatusCode;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+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 java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+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 IoTDBInsertMultiRowIT {
+ private static List<String> sqls = new ArrayList<>();
+ private static Connection connection;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ EnvFactory.getEnv().getConfig().getCommonConfig().setMaxInnerCompactionCandidateFileNum(2);
+ EnvFactory.getEnv().initClusterEnvironment();
+ initCreateSQLStatement();
+ insertData();
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ close();
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ private static void close() {
+ if (Objects.nonNull(connection)) {
+ try {
+ connection.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private static void initCreateSQLStatement() {
+ sqls.add("CREATE DATABASE t1");
+ sqls.add("USE \"t1\"");
+ sqls.add(
+ "create table wf01 (id1 string id, status boolean measurement, temperature float measurement)");
+ }
+
+ private static void insertData() throws ClassNotFoundException, SQLException {
+ connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement();
+
+ for (String sql : sqls) {
+ statement.execute(sql);
+ }
+
+ statement.close();
+ }
+
+ @Test
+ public void testInsertMultiRow() throws SQLException {
+ Statement st0 = connection.createStatement();
+ st0.execute("insert into wf01(id1, time, status) values ('wt01', 1, true)");
+ st0.execute("insert into wf01(id1, time, status) values ('wt01', 2, true), ('wt01', 3, false)");
+ st0.execute(
+ "insert into wf01(id1, time, status) values ('wt01', 4, true), ('wt01', 5, true), ('wt01', 6, false)");
+
+ st0.execute("insert into wf01(id1, time, temperature, status) values ('wt01', 7, 15.3, true)");
+ st0.execute(
+ "insert into wf01(id1, time, temperature, status) values ('wt01', 8, 18.3, false), ('wt01', 9, 23.1, false)");
+ st0.execute(
+ "insert into wf01(id1, time, temperature, status) values ('wt01', 10, 22.3, true), ('wt01', 11, 18.8, false), ('wt01', 12, 24.4, true)");
+ st0.close();
+
+ Statement st1 = connection.createStatement();
+ ResultSet rs1 = st1.executeQuery("select count(status) from wf01");
+ rs1.next();
+ long countStatus = rs1.getLong(1);
+ assertEquals(countStatus, 12L);
+
+ ResultSet rs2 = st1.executeQuery("select count(temperature) from wf01");
+ rs2.next();
+ long countTemperature = rs2.getLong(1);
+ assertEquals(countTemperature, 6L);
+
+ st1.close();
+ }
+
+ @Test(expected = Exception.class)
+ @Ignore
+ public void testInsertWithTimesColumns() throws SQLException {
+ Statement st1 = connection.createStatement();
+ st1.execute("insert into wf01(id1,time) values('wt01', 1)");
+ }
+
+ @Test
+ public void testInsertMultiRowWithMisMatchDataType() {
+ try {
+ Statement st1 = connection.createStatement();
+ st1.execute(
+ "insert into wf01(id1, time, status) values('wt01', 1, 1.0), ('wt01', 2, 'hello')");
+ fail();
+ } catch (SQLException e) {
+ assertTrue(
+ e.getMessage().contains(Integer.toString(TSStatusCode.METADATA_ERROR.getStatusCode())));
+ }
+ }
+
+ @Test
+ @Ignore // TODO: delete
+ public void testInsertMultiRowWithNull() {
+ try (Statement st1 = connection.createStatement()) {
+ st1.execute(
+ "insert into root.t1.d99.wt01(time, s1, s2) values(100, null, 1), (101, null, 2)");
+ fail();
+ } catch (SQLException e) {
+ assertTrue(
+ e.getMessage().contains(Integer.toString(TSStatusCode.METADATA_ERROR.getStatusCode())));
+ }
+ try (Statement st2 = connection.createStatement()) {
+ st2.execute("CREATE TIMESERIES root.t1.d1.s1 WITH DATATYPE=double, ENCODING=PLAIN;");
+ st2.execute(
+ "INSERT INTO root.t1.d1(time, s1) VALUES (6, 10),(7,12),(8,14),(9,160),(10,null),(11,58)");
+ } catch (SQLException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void testInsertMultiRowWithWrongTimestampPrecision() {
+ try (Statement st1 = connection.createStatement()) {
+ st1.execute(
+ "insert into wf01(id1, time, status) values('wt01', 1618283005586000, true), ('wt01', 1618283005586001, false)");
+ fail();
+ } catch (SQLException e) {
+ assertTrue(e.getMessage().contains("Current system timestamp precision is ms"));
+ }
+ }
+
+ @Test
+ public void testInsertMultiRowWithMultiTimePartition() throws Exception {
+ try (Statement st1 = connection.createStatement()) {
+ st1.execute("create table sg1 (id1 string id, s1 int32 measurement)");
+ st1.execute("insert into sg1(id1, time, s1) values('d1', 604800010,1)");
+ st1.execute("flush");
+ st1.execute("insert into sg1(id1, time, s1) values('d1', 604799990,1), ('d1', 604800001,1)");
+ st1.execute("flush");
+ ResultSet rs1 = st1.executeQuery("select time, s1 from sg1");
+ assertTrue(rs1.next());
+ assertEquals(604799990, rs1.getLong("time"));
+ assertTrue(rs1.next());
+ assertEquals(604800001, rs1.getLong("time"));
+ assertTrue(rs1.next());
+ assertEquals(604800010, rs1.getLong("time"));
+ assertFalse(rs1.next());
+ }
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertNaNIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertNaNIT.java
new file mode 100644
index 0000000..bb597bf
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertNaNIT.java
@@ -0,0 +1,199 @@
+/*
+ * 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.relational.it.db.it;
+
+import org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant;
+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.apache.iotdb.itbase.category.RemoteIT;
+
+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.Statement;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.apache.iotdb.db.utils.constant.TestConstant.TIMESTAMP_STR;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Notice that, all test begins with "IoTDB" is integration test. All test which will start the
+ * IoTDB server should be defined as integration test.
+ *
+ * <p>This test stores NaN Values and retrieves them via SQL Interface.
+ */
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class, RemoteIT.class})
+public class IoTDBInsertNaNIT {
+
+ private static final String CREATE_TEMPLATE_SQL =
+ "CREATE TIMESERIES root.vehicle.%s.%s WITH DATATYPE=%s, ENCODING=%s, 'MAX_POINT_NUMBER'='%d'";
+ private static final String INSERT_TEMPLATE_SQL =
+ "insert into root.vehicle.%s(timestamp,%s) values(%d,%s)";
+ private static final String INSERT_BRAND_NEW_TEMPLATE_SQL =
+ "insert into root.cycle.%s(timestamp,%s) values(%d,%s)";
+ private static List<String> sqls = new ArrayList<>();
+ private static final int TIMESTAMP = 10;
+ private static final String VALUE = "NaN";
+ private static final float DELTA_FLOAT = 0.0000001f;
+ private static final double DELTA_DOUBLE = 0.0000001d;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ EnvFactory.getEnv().initClusterEnvironment();
+ initCreateSQLStatement();
+ insertData();
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ private static void initCreateSQLStatement() {
+ sqls.add("CREATE DATABASE root.happy");
+ sqls.add("CREATE DATABASE root.cycle");
+ sqls.add("CREATE DATABASE root.vehicle.f0");
+ sqls.add("CREATE DATABASE root.vehicle.d0");
+ for (int i = 0; i < 10; i++) {
+ sqls.add(String.format(CREATE_TEMPLATE_SQL, "f0", "s" + i + "rle", "FLOAT", "RLE", i));
+ sqls.add(String.format(CREATE_TEMPLATE_SQL, "f0", "s" + i + "2f", "FLOAT", "TS_2DIFF", i));
+ sqls.add(String.format(CREATE_TEMPLATE_SQL, "d0", "s" + i + "rle", "DOUBLE", "RLE", i));
+ sqls.add(String.format(CREATE_TEMPLATE_SQL, "d0", "s" + i + "2f", "DOUBLE", "TS_2DIFF", i));
+ }
+ for (int i = 0; i < 10; i++) {
+ sqls.add(String.format(INSERT_TEMPLATE_SQL, "f0", "s" + i + "rle", TIMESTAMP, VALUE));
+ sqls.add(String.format(INSERT_TEMPLATE_SQL, "f0", "s" + i + "2f", TIMESTAMP, VALUE));
+ sqls.add(String.format(INSERT_TEMPLATE_SQL, "d0", "s" + i + "rle", TIMESTAMP, VALUE));
+ sqls.add(String.format(INSERT_TEMPLATE_SQL, "d0", "s" + i + "2f", TIMESTAMP, VALUE));
+ }
+ }
+
+ private static void insertData() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+
+ for (String sql : sqls) {
+ statement.execute(sql);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void selectAllSQLTest() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ int cnt;
+ try (ResultSet resultSet = statement.executeQuery("select * from root.vehicle.*")) {
+ assertNotNull(resultSet);
+ cnt = 0;
+ while (resultSet.next()) {
+ assertEquals(TIMESTAMP + "", resultSet.getString(TIMESTAMP_STR));
+ for (int i = 0; i < 10; i++) {
+ assertEquals(
+ Float.parseFloat(VALUE),
+ resultSet.getFloat(String.format("root.vehicle.%s.%s", "f0", "s" + i + "rle")),
+ DELTA_FLOAT);
+ assertEquals(
+ Float.parseFloat(VALUE),
+ resultSet.getFloat(String.format("root.vehicle.%s.%s", "f0", "s" + i + "2f")),
+ DELTA_FLOAT);
+ assertEquals(
+ Double.parseDouble(VALUE),
+ resultSet.getDouble(String.format("root.vehicle.%s.%s", "d0", "s" + i + "rle")),
+ DELTA_DOUBLE);
+ assertEquals(
+ Double.parseDouble(VALUE),
+ resultSet.getDouble(String.format("root.vehicle.%s.%s", "d0", "s" + i + "2f")),
+ DELTA_DOUBLE);
+ }
+ cnt++;
+ }
+ assertEquals(1, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void selectTest() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(
+ "CREATE TIMESERIES root.happy.device1.sensor1.temperature WITH DATATYPE=DOUBLE, ENCODING=RLE");
+ statement.execute(
+ "INSERT INTO root.happy.device1.sensor1(timestamp,temperature) values(7925, NaN)");
+ int cnt;
+ try (ResultSet resultSet =
+ statement.executeQuery("select * from root.happy.device1.sensor1")) {
+ assertNotNull(resultSet);
+ cnt = 0;
+ while (resultSet.next()) {
+ assertEquals(7925 + "", resultSet.getString(TIMESTAMP_STR));
+ assertEquals(
+ Double.parseDouble(VALUE),
+ resultSet.getDouble("root.happy.device1.sensor1.temperature"),
+ DELTA_DOUBLE);
+ cnt++;
+ }
+ assertEquals(1, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void testNaNValue() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(
+ String.format(INSERT_BRAND_NEW_TEMPLATE_SQL, "d0", "s0" + "2f", TIMESTAMP, VALUE));
+ boolean exist = false;
+ try (ResultSet resultSet = statement.executeQuery("show timeseries")) {
+ assertNotNull(resultSet);
+ while (resultSet.next()) {
+ if ((resultSet.getString(ColumnHeaderConstant.TIMESERIES)).contains("root.cycle.d0.s0")) {
+ exist = true;
+ }
+ }
+ }
+ assertTrue(exist);
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertNullIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertNullIT.java
new file mode 100644
index 0000000..75c2a70
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertNullIT.java
@@ -0,0 +1,166 @@
+/*
+ * 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.relational.it.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.apache.iotdb.itbase.category.RemoteIT;
+import org.apache.iotdb.itbase.env.BaseEnv;
+
+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.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class, RemoteIT.class})
+public class IoTDBInsertNullIT {
+ private static final List<String> sqls = new ArrayList<>();
+ private static Connection connection;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ EnvFactory.getEnv().initClusterEnvironment();
+ initCreateSQLStatement();
+ insertData();
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ close();
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ private static void close() {
+ if (Objects.nonNull(connection)) {
+ try {
+ connection.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private static void initCreateSQLStatement() {
+ sqls.add("CREATE DATABASE test");
+ sqls.add("USE \"test\"");
+ sqls.add(
+ "CREATE TABLE sg (id1 string id, s1 boolean measurement, s2 float measurement, s3 int32 measurement)");
+ }
+
+ private static void insertData() throws SQLException {
+ connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement();
+
+ for (String sql : sqls) {
+ statement.execute(sql);
+ }
+
+ statement.close();
+ }
+
+ @Test
+ public void testInsertNull() {
+ String[] retArray =
+ new String[] {
+ "1,d2,null,1.0,1,", "2,d2,true,null,2,", "3,d2,true,3.0,null,",
+ };
+
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("use \"test\"");
+ statement.execute("insert into sg(id1,time,s1,s2,s3) values('d2',1,null,1.0,1)");
+ statement.execute("insert into sg(id1,time,s1,s2,s3) values('d2',2,true,null,2)");
+ statement.execute("insert into sg(id1,time,s1,s2,s3) values('d2',3,true,3.0,null)");
+
+ try (ResultSet resultSet = statement.executeQuery("select * from sg")) {
+ assertNotNull(resultSet);
+ ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
+ List<Integer> actualIndexToExpectedIndexList =
+ checkHeader(
+ resultSetMetaData,
+ "time,id1,s1,s2,s3",
+ new int[] {
+ Types.TIMESTAMP, Types.VARCHAR, Types.BOOLEAN, Types.FLOAT, Types.INTEGER,
+ });
+
+ int cnt = 0;
+ while (resultSet.next()) {
+ String[] expectedStrings = retArray[cnt].split(",");
+ StringBuilder expectedBuilder = new StringBuilder();
+ StringBuilder actualBuilder = new StringBuilder();
+ for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
+ if (i == 1) {
+ actualBuilder.append(resultSet.getTimestamp(i).getTime()).append(",");
+ } else {
+ actualBuilder.append(resultSet.getString(i)).append(",");
+ }
+ expectedBuilder
+ .append(expectedStrings[actualIndexToExpectedIndexList.get(i - 1)])
+ .append(",");
+ }
+ assertEquals(expectedBuilder.toString(), actualBuilder.toString());
+ cnt++;
+ }
+ assertEquals(3, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ private List<Integer> checkHeader(
+ ResultSetMetaData resultSetMetaData, String expectedHeaderStrings, int[] expectedTypes)
+ throws SQLException {
+ String[] expectedHeaders = expectedHeaderStrings.split(",");
+ Map<String, Integer> expectedHeaderToTypeIndexMap = new HashMap<>();
+ for (int i = 0; i < expectedHeaders.length; ++i) {
+ expectedHeaderToTypeIndexMap.put(expectedHeaders[i], i);
+ }
+
+ List<Integer> actualIndexToExpectedIndexList = new ArrayList<>();
+ for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
+ Integer typeIndex = expectedHeaderToTypeIndexMap.get(resultSetMetaData.getColumnName(i));
+ assertNotNull(typeIndex);
+ assertEquals(expectedTypes[typeIndex], resultSetMetaData.getColumnType(i));
+ actualIndexToExpectedIndexList.add(typeIndex);
+ }
+ return actualIndexToExpectedIndexList;
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertWithoutTimeIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertWithoutTimeIT.java
new file mode 100644
index 0000000..2106626
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertWithoutTimeIT.java
@@ -0,0 +1,134 @@
+/*
+ * 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.relational.it.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.apache.iotdb.itbase.env.BaseEnv;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.apache.iotdb.db.it.utils.TestUtils.assertTableNonQueryTestFail;
+import static org.apache.iotdb.db.it.utils.TestUtils.resultSetEqualTest;
+import static org.junit.Assert.fail;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+public class IoTDBInsertWithoutTimeIT {
+
+ private static final List<String> sqls =
+ Arrays.asList(
+ "CREATE DATABASE test",
+ "USE \"test\"",
+ "CREATE TABLE sg1(id1 string id, s1 int64 measurement, s2 float measurement, s3 string measurement)");
+
+ @Before
+ public void setUp() throws Exception {
+ EnvFactory.getEnv().initClusterEnvironment();
+ createTable();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ private void createTable() {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ for (String sql : sqls) {
+ statement.execute(sql);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void testInsertWithoutTime() {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("use \"test\"");
+ statement.execute("insert into sg1(id1, s1, s2, s3) values ('d1',1, 1, '1')");
+ Thread.sleep(1);
+ statement.execute("insert into sg1(id1, s2, s1, s3) values ('d1',2, 2, '2')");
+ Thread.sleep(1);
+ statement.execute("insert into sg1(id1, s3, s2, s1) values ('d1','3', 3, 3)");
+ Thread.sleep(1);
+ statement.execute("insert into sg1(id1, s1) values ('d1',1)");
+ statement.execute("insert into sg1(id1, s2) values ('d1',2)");
+ statement.execute("insert into sg1(id1, s3) values ('d1','3')");
+ } catch (SQLException | InterruptedException e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+
+ String expectedHeader = "count(s1),count(s2),count(s3),";
+ String[] retArray = new String[] {"4,4,4,"};
+ resultSetEqualTest("select count(s1), count(s2), count(s3) from sg1", expectedHeader, retArray);
+ }
+
+ @Test
+ @Ignore // TODO: delete
+ public void testInsertWithoutValueColumns() {
+ assertTableNonQueryTestFail(
+ "insert into sg1(id1, time) values ('d1', 1)",
+ "InsertStatement should contain at least one measurement",
+ "test");
+ }
+
+ @Test
+ public void testInsertMultiRow() {
+ assertTableNonQueryTestFail(
+ "insert into sg1(s3) values ('d1', '1'), ('d1', '2')",
+ "need timestamps when insert multi rows",
+ "test");
+ assertTableNonQueryTestFail(
+ "insert into sg1(id1, s1, s2) values ('d1', 1, 1), ('d1', 2, 2)",
+ "need timestamps when insert multi rows",
+ "test");
+ }
+
+ @Test
+ public void testInsertWithMultiTimesColumns() {
+ assertTableNonQueryTestFail(
+ "insert into sg1(id1, time, time) values ('d1', 1, 1)",
+ "One row should only have one time value",
+ "test");
+ assertTableNonQueryTestFail(
+ "insert into sg1(id1, time, s1, time) values ('d1', 1, 1, 1)",
+ "One row should only have one time value",
+ "test");
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBMultiDeviceIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBMultiDeviceIT.java
new file mode 100644
index 0000000..87e6587
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBMultiDeviceIT.java
@@ -0,0 +1,359 @@
+/*
+ * 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.relational.it.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.apache.iotdb.itbase.constant.TestConstant;
+import org.apache.iotdb.itbase.env.BaseEnv;
+
+import org.junit.After;
+import org.junit.Before;
+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.Statement;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * Notice that, all test begins with "IoTDB" is integration test. All test which will start the
+ * IoTDB server should be defined as integration test.
+ */
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+public class IoTDBMultiDeviceIT {
+
+ @Before
+ public void setUp() throws Exception {
+ // use small page
+ EnvFactory.getEnv()
+ .getConfig()
+ .getCommonConfig()
+ .setMaxNumberOfPointsInPage(100)
+ .setPageSizeInByte(1024 * 15)
+ .setGroupSizeInByte(1024 * 100)
+ .setMemtableSizeThreshold(1024 * 100)
+ .setPartitionInterval(100)
+ .setQueryThreadCount(2)
+ .setCompressor("LZ4");
+
+ EnvFactory.getEnv().initClusterEnvironment();
+
+ insertData();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ private static void insertData() {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+
+ for (String sql : TestConstant.createSql) {
+ statement.addBatch(sql);
+ }
+
+ statement.addBatch("CREATE DATABASE test");
+ statement.addBatch("USE \"test\"");
+ statement.addBatch(
+ "create table t (id1 string id, id2 string id, s0 int32 measurement, s1 int32 measurement)");
+
+ // insert of data time range :0-100 into fans
+ for (int time = 0; time < 100; time++) {
+
+ String sql =
+ String.format(
+ "insert into t(id1,id2,time,s0) values('fans','d0',%s,%s)", time, time % 7);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1,id2,time,s0) values('fans','d1',%s,%s)", time, time % 4);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1,id2,time,s0) values('fans','d2',%s,%s)", time, time % 7);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1,id2,time,s0) values('fans','d3','%s,%s)", time, time % 4);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1, id2,time,s0) values('car','d0',%s,%s)", time, time % 7);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1, id2,time,s0) values('car','d1',%s,%s)", time, time % 4);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1, id2,time,s0) values('car','d2',%s,%s)", time, time % 4);
+ statement.addBatch(sql);
+ }
+
+ // insert large amount of data time range : 1370 ~ 2400
+ for (int time = 1370; time < 2400; time++) {
+
+ String sql =
+ String.format(
+ "insert into t(id1,id2,time,s0) values('fans','d0',%s,%s)", time, time % 7);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1,id2,time,s0) values('fans','d1',%s,%s)", time, time % 4);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1,id2,time,s0) values('fans','d2',%s,%s)", time, time % 7);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1,id2,time,s0) values('fans','d3','%s,%s)", time, time % 4);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1, id2,time,s0) values('car','d0',%s,%s)", time, time % 7);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1, id2,time,s0) values('car','d1',%s,%s)", time, time % 4);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1, id2,time,s0) values('car','d2',%s,%s)", time, time % 4);
+ statement.addBatch(sql);
+ }
+
+ // insert large amount of data time range : 300 ~ 1360
+ for (int time = 300; time < 1360; time++) {
+ // System.out.println("===" + time);
+ String sql =
+ String.format(
+ "insert into t(id1,id2,time,s0) values('fans','d0',%s,%s)", time, time % 7);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1,id2,time,s0) values('fans','d1',%s,%s)", time, time % 4);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1,id2,time,s0) values('fans','d2',%s,%s)", time, time % 7);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1,id2,time,s0) values('fans','d3','%s,%s)", time, time % 4);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1, id2,time,s0) values('car','d0',%s,%s)", time, time % 7);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1, id2,time,s0) values('car','d1',%s,%s)", time, time % 4);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1, id2,time,s0) values('car','d2',%s,%s)", time, time % 4);
+ statement.addBatch(sql);
+ }
+
+ statement.addBatch("flush");
+
+ // unsequential data, memory data
+ for (int time = 1000; time < 1100; time++) {
+
+ String sql =
+ String.format(
+ "insert into t(id1,id2,time,s0) values('fans','d0',%s,%s)", time, time % 7);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1,id2,time,s0) values('fans','d1',%s,%s)", time, time % 4);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1,id2,time,s0) values('fans','d2',%s,%s)", time, time % 7);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1,id2,time,s0) values('fans','d3','%s,%s)", time, time % 4);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1, id2,time,s0) values('car','d0',%s,%s)", time, time % 7);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1, id2,time,s0) values('car','d1',%s,%s)", time, time % 4);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1, id2,time,s0) values('car','d2',%s,%s)", time, time % 4);
+ statement.addBatch(sql);
+ }
+
+ // sequential data, memory data
+ for (int time = 20000; time < 20100; time++) {
+
+ String sql =
+ String.format(
+ "insert into t(id1,id2,time,s0) values('fans','d0',%s,%s)", time, time % 7);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1,id2,time,s0) values('fans','d1',%s,%s)", time, time % 4);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1,id2,time,s0) values('fans','d2',%s,%s)", time, time % 7);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1,id2,time,s0) values('fans','d3','%s,%s)", time, time % 4);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1, id2,time,s0) values('car','d0',%s,%s)", time, time % 7);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1, id2,time,s0) values('car','d1',%s,%s)", time, time % 4);
+ statement.addBatch(sql);
+ sql =
+ String.format(
+ "insert into t(id1, id2,time,s0) values('car','d2',%s,%s)", time, time % 4);
+ statement.addBatch(sql);
+ }
+ statement.executeBatch();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void testMultiDeviceQueryAndDelete() {
+ testSelectAll();
+ testSelectAfterDelete();
+ }
+
+ private void testSelectAll() {
+ String selectSql = "select * from t";
+
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("use \"test\"");
+ Map<String, Long> lastTimeMap = new HashMap<>();
+ try (ResultSet resultSet = statement.executeQuery(selectSql)) {
+ int cnt = 0;
+ while (resultSet.next()) {
+ String id = resultSet.getString("id1") + "_" + resultSet.getString("id2");
+ long before = lastTimeMap.getOrDefault(id, -1L);
+ long cur = resultSet.getTimestamp("time").getTime();
+ if (cur <= before) {
+ fail("time order wrong!");
+ }
+ lastTimeMap.put(id, cur);
+ cnt++;
+ }
+ assertEquals(13740, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ private void testSelectAfterDelete() {
+ String selectSql = "select * from t";
+
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("USE \"test\"");
+
+ statement.execute("DELETE FROM t WHERE id1='fans' and time <= 100");
+ statement.execute("DELETE FROM t WHERE id1='car' and time <= 100");
+ statement.execute("DELETE FROM t WHERE id1='fans' and time >= 20050 and time < 20100");
+ statement.execute("DELETE FROM t WHERE id1='car' and time >= 20050 and time < 20100");
+
+ try (ResultSet resultSet = statement.executeQuery(selectSql)) {
+ int cnt = 0;
+ long before = -1;
+ while (resultSet.next()) {
+ long cur = Long.parseLong(resultSet.getString("time"));
+ if (cur <= before) {
+ fail("time order wrong!");
+ }
+ before = cur;
+ cnt++;
+ }
+ assertEquals(2140, cnt);
+ }
+
+ statement.execute("DELETE FROM t WHERE id1 = 'fans' and time <= 20000");
+ statement.execute("DELETE FROM t WHERE id1 = 'car' and time <= 20000");
+
+ try (ResultSet resultSet = statement.executeQuery(selectSql)) {
+ int cnt = 0;
+ long before = -1;
+ while (resultSet.next()) {
+ long cur = resultSet.getTimestamp("time").getTime();
+ if (cur <= before) {
+ fail("time order wrong!");
+ }
+ before = cur;
+ cnt++;
+ }
+ assertEquals(49, cnt);
+ }
+
+ statement.execute("DELETE FROM t WHERE time >= 20000");
+
+ try (ResultSet resultSet = statement.executeQuery(selectSql)) {
+ int cnt = 0;
+ long before = -1;
+ while (resultSet.next()) {
+ long cur = resultSet.getTimestamp("time").getTime();
+ if (cur <= before) {
+ fail("time order wrong!");
+ }
+ before = cur;
+ cnt++;
+ }
+ assertEquals(0, cnt);
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBPartialInsertionIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBPartialInsertionIT.java
new file mode 100644
index 0000000..c3aa94c
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBPartialInsertionIT.java
@@ -0,0 +1,221 @@
+/*
+ * 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.relational.it.db.it;
+
+import org.apache.iotdb.isession.ISession;
+import org.apache.iotdb.isession.SessionDataSet;
+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.apache.iotdb.itbase.env.BaseEnv;
+
+import org.apache.tsfile.enums.TSDataType;
+import org.apache.tsfile.read.common.RowRecord;
+import org.apache.tsfile.write.record.Tablet;
+import org.apache.tsfile.write.schema.IMeasurementSchema;
+import org.apache.tsfile.write.schema.MeasurementSchema;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+public class IoTDBPartialInsertionIT {
+ private final Logger logger = LoggerFactory.getLogger(IoTDBPartialInsertionIT.class);
+
+ @Before
+ public void setUp() throws Exception {
+ EnvFactory.getEnv().getConfig().getCommonConfig().setAutoCreateSchemaEnabled(false);
+ EnvFactory.getEnv().initClusterEnvironment();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ @Test
+ public void testPartialInsertionAllFailed() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+
+ try {
+ statement.execute("CREATE DATABASE test");
+ statement.execute("USE \"test\"");
+ statement.execute("create table sg1 (id1 string id, s0 int32 measurement)");
+ statement.execute("INSERT INTO sg1(id1, timestamp, s0) VALUES ('id', 1, 1)");
+ fail();
+ } catch (SQLException e) {
+ assertTrue(e.getMessage().contains("Path [root.sg1.s0] does not exist"));
+ }
+ }
+ }
+
+ @Test
+ public void testPartialInsertionRestart() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+
+ statement.execute("CREATE DATABASE test");
+ statement.execute("USE \"test\"");
+ statement.execute(
+ "create table sg (id1 string id, s1 text measurement, s2 double measurement)");
+
+ try {
+ statement.execute("INSERT INTO sg(id1,time,s1,s2) VALUES('d1', 100,'test','test')");
+ } catch (SQLException e) {
+ // ignore
+ }
+ }
+
+ // TODO: replace restartDaemon() with new methods in Env.
+ /*
+ long time = 0;
+ try {
+ EnvironmentUtils.restartDaemon();
+ StorageEngine.getInstance().recover();
+ // wait for recover
+ while (!StorageEngine.getInstance().isAllSgReady()) {
+ Thread.sleep(500);
+ time += 500;
+ if (time > 10000) {
+ logger.warn("wait too long in restart, wait for: " + time / 1000 + "s");
+ }
+ }
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+ */
+
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("use \"test\"");
+
+ try (ResultSet resultSet = statement.executeQuery("SELECT s1 FROM sg")) {
+ assertNotNull(resultSet);
+ int cnt = 0;
+ while (resultSet.next()) {
+ cnt++;
+ assertEquals("test", resultSet.getString("s1"));
+ }
+ assertEquals(1, cnt);
+ }
+ try (ResultSet resultSet = statement.executeQuery("SELECT s2 FROM sg")) {
+ assertNotNull(resultSet);
+ assertFalse(resultSet.next());
+ }
+ }
+ }
+
+ @Test
+ public void testPartialInsertTablet() {
+ try (ISession session = EnvFactory.getEnv().getSessionConnection(BaseEnv.TABLE_SQL_DIALECT)) {
+ session.executeNonQueryStatement("create database test");
+ session.executeNonQueryStatement("use \"test\"");
+ session.executeNonQueryStatement(
+ "create table sg1 (id1 string id, s1 int64 measurement, s2 int64 measurement)");
+ List<IMeasurementSchema> schemaList = new ArrayList<>();
+ schemaList.add(new MeasurementSchema("id1", TSDataType.STRING));
+ schemaList.add(new MeasurementSchema("s1", TSDataType.INT64));
+ schemaList.add(new MeasurementSchema("s2", TSDataType.INT64));
+ schemaList.add(new MeasurementSchema("s3", TSDataType.INT64));
+ final List<Tablet.ColumnType> columnTypes =
+ Arrays.asList(
+ Tablet.ColumnType.ID,
+ Tablet.ColumnType.MEASUREMENT,
+ Tablet.ColumnType.MEASUREMENT,
+ Tablet.ColumnType.MEASUREMENT);
+ Tablet tablet = new Tablet("sg1", schemaList, columnTypes, 300);
+ long timestamp = 0;
+ for (long row = 0; row < 100; row++) {
+ int rowIndex = tablet.rowSize++;
+ tablet.addTimestamp(rowIndex, timestamp);
+ for (int s = 0; s < 4; s++) {
+ long value = timestamp;
+ if (s == 0) {
+ tablet.addValue(schemaList.get(s).getMeasurementId(), rowIndex, "d1");
+ } else {
+ tablet.addValue(schemaList.get(s).getMeasurementId(), rowIndex, value);
+ }
+ }
+ timestamp++;
+ }
+ timestamp = System.currentTimeMillis();
+ for (long row = 0; row < 100; row++) {
+ int rowIndex = tablet.rowSize++;
+ tablet.addTimestamp(rowIndex, timestamp);
+ for (int s = 0; s < 4; s++) {
+ long value = timestamp;
+ if (s == 0) {
+ tablet.addValue(schemaList.get(s).getMeasurementId(), rowIndex, "d1");
+ } else {
+ tablet.addValue(schemaList.get(s).getMeasurementId(), rowIndex, value);
+ }
+ }
+ timestamp++;
+ }
+ try {
+ session.insertRelationalTablet(tablet);
+ } catch (Exception e) {
+ if (!e.getMessage().contains("507")) {
+ fail(e.getMessage());
+ }
+ }
+ try (SessionDataSet dataSet = session.executeQueryStatement("SELECT * FROM sg1")) {
+ assertEquals(dataSet.getColumnNames().size(), 4);
+ assertEquals(dataSet.getColumnNames().get(0), "time");
+ assertEquals(dataSet.getColumnNames().get(1), "id1");
+ assertEquals(dataSet.getColumnNames().get(2), "s1");
+ assertEquals(dataSet.getColumnNames().get(3), "s2");
+ int cnt = 0;
+ while (dataSet.hasNext()) {
+ RowRecord rowRecord = dataSet.next();
+ long time = rowRecord.getFields().get(0).getLongV();
+ assertEquals(time, rowRecord.getFields().get(2).getLongV());
+ assertEquals(time, rowRecord.getFields().get(3).getLongV());
+ cnt++;
+ }
+ Assert.assertEquals(200, cnt);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBRecoverIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBRecoverIT.java
new file mode 100644
index 0000000..881e9c0
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBRecoverIT.java
@@ -0,0 +1,307 @@
+/*
+ * 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.relational.it.db.it;
+
+import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.it.env.cluster.env.AbstractEnv;
+import org.apache.iotdb.it.framework.IoTDBTestRunner;
+import org.apache.iotdb.itbase.category.ClusterIT;
+import org.apache.iotdb.itbase.category.LocalStandaloneIT;
+import org.apache.iotdb.itbase.env.BaseEnv;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.Locale;
+
+import static org.apache.iotdb.db.utils.constant.TestConstant.count;
+import static org.apache.iotdb.db.utils.constant.TestConstant.maxValue;
+import static org.apache.iotdb.db.utils.constant.TestConstant.minTime;
+import static org.apache.iotdb.db.utils.constant.TestConstant.minValue;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+public class IoTDBRecoverIT {
+
+ private static final Logger logger = LoggerFactory.getLogger(IoTDBRecoverIT.class);
+
+ private static final String TIMESTAMP_STR = "Time";
+ private static final String TEMPERATURE_STR = "temperature";
+ private static final String[] creationSqls =
+ new String[] {
+ "CREATE DATABASE test",
+ "USE \"test\"",
+ "CREATE TABLE vehicle (id1 string id, s0 int32 measurement, s1 int64 measurement, s2 float measurement, s3 text measurement, s4 boolean measurement)"
+ };
+ private static final String[] dataSet2 =
+ new String[] {
+ "CREATE DATABASE ln",
+ "USE \"ln\"",
+ "CREATE TABLE wf01 (id1 string id, status boolean measurement, temperature float measurement, hardware int32 measurement)",
+ "INSERT INTO wf01(id1, time,temperature,status, hardware) "
+ + "values('wt01', 1, 1.1, false, 11)",
+ "INSERT INTO wf01(id1, time,temperature,status, hardware) "
+ + "values('wt01', 2, 2.2, true, 22)",
+ "INSERT INTO wf01(id1, time,temperature,status, hardware) "
+ + "values('wt01', 3, 3.3, false, 33 )",
+ "INSERT INTO wf01(id1, time,temperature,status, hardware) "
+ + "values('wt01', 4, 4.4, false, 44)",
+ "INSERT INTO wf01(id1, time,temperature,status, hardware) "
+ + "values('wt01',5, 5.5, false, 55)"
+ };
+ private final String d0s0 = "s0";
+ private final String d0s1 = "s1";
+ private final String d0s2 = "s2";
+ private final String d0s3 = "s3";
+
+ @Before
+ public void setUp() throws Exception {
+ EnvFactory.getEnv().initClusterEnvironment();
+ prepareData();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ @Test
+ public void recoverTest1() {
+ // stop cluster
+ EnvFactory.getEnv().shutdownAllDataNodes();
+ logger.info("All DataNodes are shut down");
+ EnvFactory.getEnv().shutdownAllConfigNodes();
+ logger.info("All ConfigNodes are shut down");
+ EnvFactory.getEnv().startAllConfigNodes();
+ logger.info("All ConfigNodes are started");
+ EnvFactory.getEnv().startAllDataNodes();
+ logger.info("All DataNodes are started");
+ // check cluster whether restart
+ ((AbstractEnv) EnvFactory.getEnv()).checkClusterStatusWithoutUnknown();
+ String[] retArray = new String[] {"0,2", "0,4", "0,3"};
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+
+ statement.execute("use \"ln\"");
+ String selectSql = "select count(temperature) from wf01 where time > 3";
+ try (ResultSet resultSet = statement.executeQuery(selectSql)) {
+ assertNotNull(resultSet);
+ resultSet.next();
+ String ans =
+ resultSet.getString("time") + "," + resultSet.getString(count(TEMPERATURE_STR));
+ Assert.assertEquals(retArray[0], ans);
+ }
+
+ selectSql = "select min_time(temperature) from wf01 where time > 3";
+ try (ResultSet resultSet = statement.executeQuery(selectSql)) {
+ assertNotNull(resultSet);
+ resultSet.next();
+ String ans =
+ resultSet.getString("time") + "," + resultSet.getString(minTime(TEMPERATURE_STR));
+ Assert.assertEquals(retArray[1], ans);
+ }
+
+ selectSql = "select min_time(temperature) from wf01 where temperature > 3";
+ try (ResultSet resultSet = statement.executeQuery(selectSql)) {
+ assertNotNull(resultSet);
+ resultSet.next();
+ String ans =
+ resultSet.getString("time") + "," + resultSet.getString(minTime(TEMPERATURE_STR));
+ Assert.assertEquals(retArray[2], ans);
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+
+ // max min ValueTest
+ retArray = new String[] {"0,8499,500.0", "0,2499,500.0"};
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+
+ String selectSql =
+ "select max_value(s0),min_value(s2) "
+ + "from root.vehicle.d0 where time >= 100 and time < 9000";
+ try (ResultSet resultSet = statement.executeQuery(selectSql)) {
+ assertNotNull(resultSet);
+ resultSet.next();
+ String ans =
+ resultSet.getString("time")
+ + ","
+ + resultSet.getString(maxValue(d0s0))
+ + ","
+ + resultSet.getString(minValue(d0s2));
+ Assert.assertEquals(retArray[0], ans);
+ }
+
+ selectSql = "select max_value(s0),min_value(s2) from root.vehicle.d0 where time < 2500";
+ try (ResultSet resultSet = statement.executeQuery(selectSql)) {
+ assertNotNull(resultSet);
+ resultSet.next();
+ String ans =
+ resultSet.getString("time")
+ + ","
+ + resultSet.getString(maxValue(d0s0))
+ + ","
+ + resultSet.getString(minValue(d0s2));
+ Assert.assertEquals(retArray[1], ans);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void recoverTest2() {
+ // stop cluster
+ EnvFactory.getEnv().shutdownAllDataNodes();
+ logger.info("All DataNodes are shut down");
+ EnvFactory.getEnv().shutdownAllConfigNodes();
+ logger.info("All ConfigNodes are shut down");
+ EnvFactory.getEnv().startAllConfigNodes();
+ logger.info("All ConfigNodes are started");
+ EnvFactory.getEnv().startAllDataNodes();
+ logger.info("All DataNodes are started");
+ // wait for cluster to start and check
+ ((AbstractEnv) EnvFactory.getEnv()).checkClusterStatusWithoutUnknown();
+ // count test
+ String[] retArray = new String[] {"0,2001,2001,2001,2001", "0,7500,7500,7500,7500"};
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+
+ String selectSql =
+ "select count(s0),count(s1),count(s2),count(s3) "
+ + "from vehicle where time >= 6000 and time <= 9000";
+ try (ResultSet resultSet = statement.executeQuery(selectSql)) {
+ assertNotNull(resultSet);
+ resultSet.next();
+ String ans =
+ resultSet.getString("time")
+ + ","
+ + resultSet.getString(count(d0s0))
+ + ","
+ + resultSet.getString(count(d0s1))
+ + ","
+ + resultSet.getString(count(d0s2))
+ + ","
+ + resultSet.getString(count(d0s3));
+ Assert.assertEquals(retArray[0], ans);
+ }
+
+ selectSql = "select count(s0),count(s1),count(s2),count(s3) from vehicle";
+ try (ResultSet resultSet = statement.executeQuery(selectSql)) {
+ assertNotNull(resultSet);
+ resultSet.next();
+ String ans =
+ resultSet.getString("time")
+ + ","
+ + resultSet.getString(count(d0s0))
+ + ","
+ + resultSet.getString(count(d0s1))
+ + ","
+ + resultSet.getString(count(d0s2))
+ + ","
+ + resultSet.getString(count(d0s3));
+ Assert.assertEquals(retArray[1], ans);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ private void prepareData() {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+
+ for (String sql : creationSqls) {
+ statement.execute(sql);
+ }
+
+ for (String sql : dataSet2) {
+ statement.execute(sql);
+ }
+
+ // prepare BufferWrite file
+ String insertTemplate =
+ "INSERT INTO vehicle(id1,timestamp,s0,s1,s2,s3,s4)" + " VALUES('d0',%d,%d,%d,%f,%s,%s)";
+ for (int i = 5000; i < 7000; i++) {
+ statement.addBatch(
+ String.format(
+ Locale.ENGLISH, insertTemplate, i, i, i, (double) i, "'" + i + "'", "true"));
+ }
+ statement.executeBatch();
+ statement.execute("flush");
+ for (int i = 7500; i < 8500; i++) {
+ statement.addBatch(
+ String.format(
+ Locale.ENGLISH, insertTemplate, i, i, i, (double) i, "'" + i + "'", "false"));
+ }
+ statement.executeBatch();
+ statement.execute("flush");
+ // prepare Unseq-File
+ for (int i = 500; i < 1500; i++) {
+ statement.addBatch(
+ String.format(
+ Locale.ENGLISH, insertTemplate, i, i, i, (double) i, "'" + i + "'", "true"));
+ }
+ statement.executeBatch();
+ statement.execute("flush");
+ for (int i = 3000; i < 6500; i++) {
+ statement.addBatch(
+ String.format(
+ Locale.ENGLISH, insertTemplate, i, i, i, (double) i, "'" + i + "'", "false"));
+ }
+ statement.executeBatch();
+ statement.execute("flush");
+
+ // prepare BufferWrite cache
+ for (int i = 9000; i < 10000; i++) {
+ statement.addBatch(
+ String.format(
+ Locale.ENGLISH, insertTemplate, i, i, i, (double) i, "'" + i + "'", "true"));
+ }
+ statement.executeBatch();
+ // prepare Overflow cache
+ for (int i = 2000; i < 2500; i++) {
+ statement.addBatch(
+ String.format(
+ Locale.ENGLISH, insertTemplate, i, i, i, (double) i, "'" + i + "'", "false"));
+ }
+ statement.executeBatch();
+ statement.execute("flush");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBRecoverUnclosedIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBRecoverUnclosedIT.java
new file mode 100644
index 0000000..29f4e5b
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBRecoverUnclosedIT.java
@@ -0,0 +1,257 @@
+/*
+ * 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.relational.it.db.it;
+
+import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.it.env.cluster.env.AbstractEnv;
+import org.apache.iotdb.it.framework.IoTDBTestRunner;
+import org.apache.iotdb.itbase.category.ClusterIT;
+import org.apache.iotdb.itbase.category.LocalStandaloneIT;
+import org.apache.iotdb.itbase.env.BaseEnv;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Locale;
+
+import static org.apache.iotdb.db.utils.constant.TestConstant.count;
+import static org.apache.iotdb.db.utils.constant.TestConstant.maxValue;
+import static org.apache.iotdb.db.utils.constant.TestConstant.minTime;
+import static org.apache.iotdb.db.utils.constant.TestConstant.minValue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+public class IoTDBRecoverUnclosedIT {
+ private static final Logger logger = LoggerFactory.getLogger(IoTDBRecoverUnclosedIT.class);
+ private static final String TIMESTAMP_STR = "time";
+ private static final String TEMPERATURE_STR = "temperature";
+ private static final String[] creationSqls =
+ new String[] {
+ "CREATE DATABASE test",
+ "USE \"test\"",
+ "CREATE TABLE vehicle (id1 string id, s0 int32 measurement, s1 int64 measurement, s2 float measurement, s3 text measurement, s4 boolean measurement)"
+ };
+ private static final String[] dataSet2 =
+ new String[] {
+ "CREATE DATABASE ln",
+ "USE \"ln\"",
+ "CREATE TABLE wf01 (id1 string id, status boolean measurement, temperature float measurement, hardware int32 measurement)",
+ "INSERT INTO wf01(id1, time,temperature,status, hardware) "
+ + "values('wt01', 1, 1.1, false, 11)",
+ "INSERT INTO wf01(id1, time,temperature,status, hardware) "
+ + "values('wt01', 2, 2.2, true, 22)",
+ "INSERT INTO wf01(id1, time,temperature,status, hardware) "
+ + "values('wt01', 3, 3.3, false, 33 )",
+ "INSERT INTO wf01(id1, time,temperature,status, hardware) "
+ + "values('wt01', 4, 4.4, false, 44)",
+ "INSERT INTO wf01(id1, time,temperature,status, hardware) "
+ + "values('wt01',5, 5.5, false, 55)"
+ };
+
+ @Before
+ public void setUp() throws Exception {
+ EnvFactory.getEnv().getConfig().getCommonConfig().setWalMode("SYNC");
+ EnvFactory.getEnv().initClusterEnvironment();
+ prepareData();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ @Test
+ public void test() throws SQLException, IOException {
+ String[] retArray = new String[] {"0,2", "0,4", "0,3"};
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+
+ statement.execute("use \"ln\"");
+ String selectSql = "select count(temperature) from wf01 where time > 3";
+ try (ResultSet resultSet = statement.executeQuery(selectSql)) {
+ assertNotNull(resultSet);
+ resultSet.next();
+ String ans =
+ resultSet.getString("time") + "," + resultSet.getString(count(TEMPERATURE_STR));
+ assertEquals(retArray[0], ans);
+ }
+
+ selectSql = "select min_time(temperature) from wf01 where time > 3";
+ try (ResultSet resultSet = statement.executeQuery(selectSql)) {
+ assertNotNull(resultSet);
+ resultSet.next();
+ String ans =
+ resultSet.getString("time") + "," + resultSet.getString(minTime(TEMPERATURE_STR));
+ assertEquals(retArray[1], ans);
+ }
+
+ selectSql = "select min_time(temperature) from wf01 where temperature > 3";
+ try (ResultSet resultSet = statement.executeQuery(selectSql)) {
+ assertNotNull(resultSet);
+ resultSet.next();
+ String ans =
+ resultSet.getString("time") + "," + resultSet.getString(minTime(TEMPERATURE_STR));
+ assertEquals(retArray[2], ans);
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+
+ insertMoreData();
+
+ // stop cluster
+ EnvFactory.getEnv().shutdownAllDataNodes();
+ logger.info("All DataNodes are shut down");
+ EnvFactory.getEnv().shutdownAllConfigNodes();
+ logger.info("All ConfigNodes are shut down");
+ EnvFactory.getEnv().startAllConfigNodes();
+ logger.info("All ConfigNodes are started");
+ EnvFactory.getEnv().startAllDataNodes();
+ logger.info("All DataNodes are started");
+ // wait for cluster to start and check
+ ((AbstractEnv) EnvFactory.getEnv()).checkClusterStatusWithoutUnknown();
+
+ // test count,
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ String selectSql = "select count(*) from vehicle";
+ ResultSet tempResultSet = statement.executeQuery(selectSql);
+ assertNotNull(tempResultSet);
+ tempResultSet.next();
+ String d0s0 = "s0";
+ String d0s1 = "s1";
+ String d0s2 = "s2";
+ assertEquals(7500, tempResultSet.getInt("count(" + d0s0 + ")"));
+
+ // test max, min value
+ retArray = new String[] {"0,8499,500.0", "0,2499,500.0"};
+ selectSql =
+ "select max_value(s0),min_value(s2) " + "from vehicle where time >= 100 and time < 9000";
+ try (ResultSet resultSet = statement.executeQuery(selectSql)) {
+ assertNotNull(resultSet);
+ resultSet.next();
+ String ans =
+ resultSet.getString(TIMESTAMP_STR)
+ + ","
+ + resultSet.getString(maxValue(d0s0))
+ + ","
+ + resultSet.getString(minValue(d0s2));
+ assertEquals(retArray[0], ans);
+ }
+
+ selectSql = "select max_value(s1),min_value(s2) from vehicle where time < 2500";
+ try (ResultSet resultSet = statement.executeQuery(selectSql)) {
+ assertNotNull(resultSet);
+ resultSet.next();
+ String ans =
+ resultSet.getString("time")
+ + ","
+ + resultSet.getString(maxValue(d0s1))
+ + ","
+ + resultSet.getString(minValue(d0s2));
+ assertEquals(retArray[1], ans);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ private void prepareData() {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ for (String sql : creationSqls) {
+ statement.execute(sql);
+ }
+
+ for (String sql : dataSet2) {
+ statement.execute(sql);
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void insertMoreData() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+
+ // prepare BufferWrite file
+ String insertTemplate =
+ "INSERT INTO vehicle(id1,timestamp,s0,s1,s2,s3,s4)" + " VALUES('d0',%d,%d,%d,%f,%s,%s)";
+ for (int i = 5000; i < 7000; i++) {
+ statement.addBatch(
+ String.format(
+ Locale.ENGLISH, insertTemplate, i, i, i, (double) i, "'" + i + "'", "true"));
+ }
+ statement.executeBatch();
+ for (int i = 7500; i < 8500; i++) {
+ statement.addBatch(
+ String.format(
+ Locale.ENGLISH, insertTemplate, i, i, i, (double) i, "'" + i + "'", "false"));
+ }
+ statement.executeBatch();
+ // prepare Unseq-File
+ for (int i = 500; i < 1500; i++) {
+ statement.addBatch(
+ String.format(
+ Locale.ENGLISH, insertTemplate, i, i, i, (double) i, "'" + i + "'", "true"));
+ }
+ for (int i = 3000; i < 6500; i++) {
+ statement.addBatch(
+ String.format(
+ Locale.ENGLISH, insertTemplate, i, i, i, (double) i, "'" + i + "'", "false"));
+ }
+ statement.executeBatch();
+ // prepare BufferWrite cache
+ for (int i = 9000; i < 10000; i++) {
+ statement.addBatch(
+ String.format(
+ Locale.ENGLISH, insertTemplate, i, i, i, (double) i, "'" + i + "'", "true"));
+ }
+ statement.executeBatch();
+ // prepare Overflow cache
+ for (int i = 2000; i < 2500; i++) {
+ statement.addBatch(
+ String.format(
+ Locale.ENGLISH, insertTemplate, i, i, i, (double) i, "'" + i + "'", "false"));
+ }
+ statement.executeBatch();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBRestartIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBRestartIT.java
new file mode 100644
index 0000000..f17f80e
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBRestartIT.java
@@ -0,0 +1,388 @@
+/*
+ * 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.relational.it.db.it;
+
+import org.apache.iotdb.db.conf.IoTDBConfig;
+import org.apache.iotdb.db.conf.IoTDBDescriptor;
+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.apache.iotdb.itbase.env.BaseEnv;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import static org.apache.iotdb.db.utils.constant.TestConstant.TIMESTAMP_STR;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+@Ignore
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+public class IoTDBRestartIT {
+
+ private final Logger logger = LoggerFactory.getLogger(IoTDBRestartIT.class);
+
+ @Before
+ public void setUp() throws Exception {
+ EnvFactory.getEnv().initClusterEnvironment();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ @Test
+ public void testRestart() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("create database test");
+ statement.execute("use \"test\"");
+ statement.execute("create table turbine (id1 string id, s1 float measurement)");
+ statement.execute("insert into turbine(id1, timestamp,s1) values('d1', 1,1.0)");
+ statement.execute("flush");
+ }
+
+ try {
+ // TODO: replace restartDaemon() with new methods in Env.
+ // EnvironmentUtils.restartDaemon();
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("insert into turbine(id1, timestamp,s1) values('d1', 2,1.0)");
+ }
+
+ try {
+ // EnvironmentUtils.restartDaemon();
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("insert into turbine(id1, timestamp,s1) values('d1', 3,1.0)");
+
+ String[] exp = new String[] {"1,1.0", "2,1.0", "3,1.0"};
+ int cnt = 0;
+ try (ResultSet resultSet = statement.executeQuery("SELECT s1 FROM turbine")) {
+ assertNotNull(resultSet);
+ while (resultSet.next()) {
+ String result = resultSet.getString("time") + "," + resultSet.getString(2);
+ assertEquals(exp[cnt], result);
+ cnt++;
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testRestartDelete() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("insert into root.turbine.d1(timestamp,s1) values(1,1)");
+ statement.execute("insert into root.turbine.d1(timestamp,s1) values(2,2)");
+ statement.execute("insert into root.turbine.d1(timestamp,s1) values(3,3)");
+ }
+
+ long time = 0;
+ /*
+ try {
+ EnvironmentUtils.restartDaemon();
+ StorageEngine.getInstance().recover();
+ // wait for recover
+ while (!StorageEngine.getInstance().isAllSgReady()) {
+ Thread.sleep(500);
+ time += 500;
+ if (time > 10000) {
+ logger.warn("wait too long in restart, wait for: " + time / 1000 + "s");
+ }
+ }
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+ */
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("delete from root.turbine.d1.s1 where time<=1");
+
+ ResultSet resultSet = statement.executeQuery("SELECT s1 FROM root.turbine.d1");
+ assertNotNull(resultSet);
+ String[] exp = new String[] {"2,2.0", "3,3.0"};
+ int cnt = 0;
+ try {
+ while (resultSet.next()) {
+ String result = resultSet.getString(TIMESTAMP_STR) + "," + resultSet.getString(2);
+ assertEquals(exp[cnt], result);
+ cnt++;
+ }
+
+ statement.execute("flush");
+ statement.execute("delete from root.turbine.d1.s1 where time<=2");
+
+ exp = new String[] {"3,3.0"};
+ resultSet = statement.executeQuery("SELECT s1 FROM root.turbine.d1");
+ assertNotNull(resultSet);
+ cnt = 0;
+ while (resultSet.next()) {
+ String result = resultSet.getString(TIMESTAMP_STR) + "," + resultSet.getString(2);
+ assertEquals(exp[cnt], result);
+ cnt++;
+ }
+ } finally {
+ resultSet.close();
+ }
+ }
+ }
+
+ @Test
+ public void testRestartQueryLargerThanEndTime() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("insert into root.turbine.d1(timestamp,s1) values(1,1)");
+ statement.execute("insert into root.turbine.d1(timestamp,s1) values(2,2)");
+ }
+
+ try {
+ // EnvironmentUtils.restartDaemon();
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("insert into root.turbine.d1(timestamp,s1) values(3,1)");
+ statement.execute("insert into root.turbine.d1(timestamp,s1) values(4,2)");
+ }
+
+ try {
+ // EnvironmentUtils.restartDaemon();
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+
+ String[] exp =
+ new String[] {
+ "4,2.0",
+ };
+ int cnt = 0;
+ try (ResultSet resultSet =
+ statement.executeQuery("SELECT s1 FROM root.turbine.d1 where time > 3")) {
+ assertNotNull(resultSet);
+ while (resultSet.next()) {
+ String result = resultSet.getString(TIMESTAMP_STR) + "," + resultSet.getString(2);
+ assertEquals(exp[cnt], result);
+ cnt++;
+ }
+ }
+ assertEquals(1, cnt);
+ }
+ }
+
+ @Test
+ public void testRestartEndTime() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("insert into root.turbine.d1(timestamp,s1) values(1,1)");
+ statement.execute("insert into root.turbine.d1(timestamp,s1) values(2,2)");
+ }
+
+ try {
+ // EnvironmentUtils.restartDaemon();
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("insert into root.turbine.d1(timestamp,s2) values(1,1)");
+ statement.execute("insert into root.turbine.d1(timestamp,s2) values(2,2)");
+ }
+
+ try {
+ // EnvironmentUtils.restartDaemon();
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+
+ String[] exp = new String[] {"1,1.0", "2,2.0"};
+ int cnt = 0;
+ try (ResultSet resultSet = statement.executeQuery("SELECT s2 FROM root.turbine.d1")) {
+ assertNotNull(resultSet);
+ while (resultSet.next()) {
+ String result = resultSet.getString(TIMESTAMP_STR) + "," + resultSet.getString(2);
+ assertEquals(exp[cnt], result);
+ cnt++;
+ }
+ }
+ assertEquals(2, cnt);
+ }
+ }
+
+ @Test
+ public void testRecoverWALMismatchDataType() throws Exception {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("insert into root.turbine1.d1(timestamp,s1,s2) values(1,1.1,2.2)");
+ statement.execute("delete timeseries root.turbine1.d1.s1");
+ statement.execute(
+ "create timeseries root.turbine1.d1.s1 with datatype=INT32, encoding=RLE, compression=SNAPPY");
+ }
+
+ // EnvironmentUtils.restartDaemon();
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+
+ try (ResultSet resultSet = statement.executeQuery("select * from root.**")) {
+ assertNotNull(resultSet);
+ int cnt = 0;
+ assertEquals(3, resultSet.getMetaData().getColumnCount());
+ while (resultSet.next()) {
+ assertEquals("1", resultSet.getString(1));
+ assertNull(resultSet.getString(2));
+ assertEquals("2.2", resultSet.getString(3));
+ cnt++;
+ }
+ assertEquals(1, cnt);
+ }
+ }
+ }
+
+ @Test
+ public void testRecoverWALDeleteSchema() throws Exception {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("insert into root.turbine1.d1(timestamp,s1,s2) values(1,1.1,2.2)");
+ statement.execute("delete timeseries root.turbine1.d1.s1");
+ }
+
+ // EnvironmentUtils.restartDaemon();
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+
+ try (ResultSet resultSet = statement.executeQuery("select * from root.**")) {
+ assertNotNull(resultSet);
+ int cnt = 0;
+ assertEquals(2, resultSet.getMetaData().getColumnCount());
+ while (resultSet.next()) {
+ assertEquals("1", resultSet.getString(1));
+ assertEquals("2.2", resultSet.getString(2));
+ cnt++;
+ }
+ assertEquals(1, cnt);
+ }
+ }
+ }
+
+ @Test
+ public void testRecoverWALDeleteSchemaCheckResourceTime() throws Exception {
+ IoTDBConfig config = IoTDBDescriptor.getInstance().getConfig();
+ int avgSeriesPointNumberThreshold = config.getAvgSeriesPointNumberThreshold();
+ config.setAvgSeriesPointNumberThreshold(2);
+ long tsFileSize = config.getSeqTsFileSize();
+ long unFsFileSize = config.getSeqTsFileSize();
+ config.setSeqTsFileSize(10000000);
+ config.setUnSeqTsFileSize(10000000);
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("create timeseries root.turbine1.d1.s1 with datatype=INT64");
+ statement.execute("insert into root.turbine1.d1(timestamp,s1) values(1,1)");
+ statement.execute("insert into root.turbine1.d1(timestamp,s1) values(2,1)");
+ statement.execute("create timeseries root.turbine1.d1.s2 with datatype=BOOLEAN");
+ statement.execute("insert into root.turbine1.d1(timestamp,s2) values(3,true)");
+ statement.execute("insert into root.turbine1.d1(timestamp,s2) values(4,true)");
+ }
+
+ Thread.sleep(1000);
+ // EnvironmentUtils.restartDaemon();
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+
+ long[] result = new long[] {1L, 2L};
+ ResultSet resultSet =
+ statement.executeQuery("select s1 from root.turbine1.d1 where time < 3");
+ assertNotNull(resultSet);
+ int cnt = 0;
+ while (resultSet.next()) {
+ assertEquals(resultSet.getLong(1), result[cnt]);
+ cnt++;
+ }
+ assertEquals(2, cnt);
+ }
+
+ config.setAvgSeriesPointNumberThreshold(avgSeriesPointNumberThreshold);
+ config.setSeqTsFileSize(tsFileSize);
+ config.setUnSeqTsFileSize(unFsFileSize);
+ }
+
+ @Test
+ public void testRecoverFromFlushMemTableError() throws Exception {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("insert into root.turbine1.d1(timestamp,s1,s2) values(1,1.1,2.2)");
+ }
+
+ // mock exception during flush memtable
+ // EnvironmentUtils.restartDaemon();
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+
+ try (ResultSet resultSet = statement.executeQuery("select * from root.**")) {
+ assertNotNull(resultSet);
+ int cnt = 0;
+ while (resultSet.next()) {
+ assertEquals("1", resultSet.getString(1));
+ assertEquals("1.1", resultSet.getString(2));
+ assertEquals("2.2", resultSet.getString(3));
+ cnt++;
+ }
+ assertEquals(1, cnt);
+ }
+ }
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBSameMeasurementsDifferentTypesIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBSameMeasurementsDifferentTypesIT.java
new file mode 100644
index 0000000..2197155
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBSameMeasurementsDifferentTypesIT.java
@@ -0,0 +1,158 @@
+/*
+ * 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.relational.it.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.apache.iotdb.itbase.constant.TestConstant;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+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.Statement;
+
+import static org.junit.Assert.fail;
+
+/**
+ * Notice that, all test begins with "IoTDB" is integration test. All test which will start the
+ * IoTDB server should be defined as integration test.
+ */
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+@Ignore
+// TODO: Delete this IT
+public class IoTDBSameMeasurementsDifferentTypesIT {
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ // use small page
+ EnvFactory.getEnv()
+ .getConfig()
+ .getCommonConfig()
+ .setMaxNumberOfPointsInPage(1000)
+ .setPageSizeInByte(1024 * 150)
+ .setGroupSizeInByte(1024 * 1000)
+ .setMemtableSizeThreshold(1024 * 1000);
+
+ EnvFactory.getEnv().initClusterEnvironment();
+
+ insertData();
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ private static void insertData() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+
+ statement.execute("CREATE DATABASE root.fans");
+ statement.execute("CREATE TIMESERIES root.fans.d0.s0 WITH DATATYPE=INT32, ENCODING=RLE");
+ statement.execute("CREATE TIMESERIES root.fans.d1.s0 WITH DATATYPE=INT64, ENCODING=RLE");
+
+ for (int time = 1; time < 10; time++) {
+
+ String sql =
+ String.format("insert into root.fans.d0(timestamp,s0) values(%s,%s)", time, time % 10);
+ statement.execute(sql);
+ sql = String.format("insert into root.fans.d1(timestamp,s0) values(%s,%s)", time, time % 5);
+ statement.execute(sql);
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void selectAllTest() {
+ String[] retArray =
+ new String[] {
+ "1,1,1", "2,2,2", "3,3,3", "4,4,4", "5,5,0", "6,6,1", "7,7,2", "8,8,3", "9,9,4"
+ };
+
+ String selectSql = "select * from root.**";
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement1 = connection.createStatement();
+ Statement statement2 = connection.createStatement()) {
+ statement1.setFetchSize(10);
+ ResultSet resultSet1 = statement1.executeQuery(selectSql);
+ int cnt1 = 0;
+ while (resultSet1.next() && cnt1 < 5) {
+ String ans =
+ resultSet1.getString(TestConstant.TIMESTAMP_STR)
+ + ","
+ + resultSet1.getString("root.fans.d0.s0")
+ + ","
+ + resultSet1.getString("root.fans.d1.s0");
+ Assert.assertEquals(retArray[cnt1], ans);
+ cnt1++;
+ }
+
+ statement2.setFetchSize(10);
+ ResultSet resultSet2 = statement2.executeQuery(selectSql);
+ int cnt2 = 0;
+ while (resultSet2.next()) {
+ String ans =
+ resultSet2.getString(TestConstant.TIMESTAMP_STR)
+ + ","
+ + resultSet2.getString("root.fans.d0.s0")
+ + ","
+ + resultSet2.getString("root.fans.d1.s0");
+ Assert.assertEquals(retArray[cnt2], ans);
+ cnt2++;
+ }
+ Assert.assertEquals(9, cnt2);
+
+ // use do-while instead of while because in the previous while loop, we have executed the next
+ // function,
+ // and the cursor has been moved to the next position, so we should fetch that value first.
+ do {
+ String ans =
+ resultSet1.getString(TestConstant.TIMESTAMP_STR)
+ + ","
+ + resultSet1.getString("root.fans.d0.s0")
+ + ","
+ + resultSet1.getString("root.fans.d1.s0");
+ Assert.assertEquals(retArray[cnt1], ans);
+ cnt1++;
+ } while (resultSet1.next());
+ // Although the statement2 has the same sql as statement1, they shouldn't affect each other.
+ // So the statement1's ResultSet should also have 9 rows in total.
+ Assert.assertEquals(9, cnt1);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ }
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/aligned/IoTDBInsertAlignedValues2IT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/aligned/IoTDBInsertAlignedValues2IT.java
new file mode 100644
index 0000000..a44d1c8
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/aligned/IoTDBInsertAlignedValues2IT.java
@@ -0,0 +1,186 @@
+/*
+ * 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.relational.it.db.it.aligned;
+
+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.apache.iotdb.itbase.env.BaseEnv;
+
+import org.junit.After;
+import org.junit.Before;
+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;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+public class IoTDBInsertAlignedValues2IT {
+
+ @Before
+ public void setUp() throws Exception {
+ EnvFactory.getEnv()
+ .getConfig()
+ .getCommonConfig()
+ .setAutoCreateSchemaEnabled(true)
+ .setMaxNumberOfPointsInPage(2);
+ EnvFactory.getEnv().initClusterEnvironment();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ @Test
+ public void testInsertAlignedWithEmptyPage() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("create database lz");
+ statement.execute("use \"lz\"");
+ statement.execute(
+ "create table dev (id1 string id, s1 int32 measurement, s2 int32 measurement, s3 int32 measurement)");
+ for (int i = 0; i < 100; i++) {
+ if (i == 99) {
+ statement.addBatch(
+ "insert into dev(id1,time,s1,s3) values("
+ + "'GPS''"
+ + ","
+ + i
+ + ","
+ + i
+ + ","
+ + i
+ + ")");
+ } else {
+ statement.addBatch(
+ "insert into dev(id1, time,s1,s2) values("
+ + "'GPS'"
+ + ","
+ + i
+ + ","
+ + i
+ + ","
+ + i
+ + ")");
+ }
+ }
+ statement.executeBatch();
+
+ statement.execute("flush");
+ int rowCount = 0;
+ try (ResultSet resultSet = statement.executeQuery("select time, s3 from dev")) {
+ while (resultSet.next()) {
+ assertEquals(99, resultSet.getInt(2));
+ rowCount++;
+ }
+ assertEquals(1, rowCount);
+ }
+
+ try (ResultSet resultSet = statement.executeQuery("select time, s2 from dev")) {
+ rowCount = 0;
+ while (resultSet.next()) {
+ assertEquals(rowCount, resultSet.getInt(2));
+ rowCount++;
+ }
+ assertEquals(99, rowCount);
+ }
+
+ try (ResultSet resultSet = statement.executeQuery("select time, s1 from dev")) {
+ rowCount = 0;
+ while (resultSet.next()) {
+ assertEquals(rowCount, resultSet.getInt(2));
+ rowCount++;
+ }
+ assertEquals(100, rowCount);
+ }
+ }
+ }
+
+ @Test
+ public void testInsertAlignedWithEmptyPage2() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("create database test");
+ statement.execute("use \"test\"");
+ statement.execute(
+ "create table sg (id1 string id, s1 string measurement, s2 string measurement)");
+
+ statement.execute("insert into sg(id1, time, s1, s2) values('d1', 1,'aa','bb')");
+ statement.execute("insert into sg(id1, time, s1, s2) values('d1', 1,'aa','bb')");
+ statement.execute("insert into sg(id1, time, s1, s2) values('d2', 1,'aa','bb')");
+ statement.execute("flush");
+ statement.execute("insert into sg(id1, time, s1, s2) values('d1', 1,'aa','bb')");
+ }
+ }
+
+ @Test
+ public void testInsertComplexAlignedValues() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.addBatch("create database test");
+ statement.addBatch("use database \"test\"");
+ statement.addBatch(
+ "create table sg (id1 string id, s1 int32 measurement, s2 int32 measurement)");
+ statement.addBatch("insert into sg(id1, time, s1) values('id1', 3,1)");
+ statement.addBatch("insert into sg(id1, time, s1) values('id1', 3,1)");
+ statement.addBatch("insert into sg(id1, time, s1) values('id1', 1,1)");
+ statement.addBatch("insert into sg(id1, time, s1) values('id1', 2,1)");
+ statement.addBatch("insert into sg(id1, time, s2) values('id1', 2,2)");
+ statement.addBatch("insert into sg(id1, time, s2) values('id1', 1,2)");
+ statement.addBatch("insert into sg(id1, time, s2) values('id1', 3,2)");
+ statement.addBatch("insert into sg(id1, time, s3) values('id1', 1,3)");
+ statement.addBatch("insert into sg(id1, time, s3) values('id1', 3,3)");
+ statement.executeBatch();
+
+ try (ResultSet resultSet =
+ statement.executeQuery("select count(s1), count(s2), count(s3) from sg")) {
+
+ assertTrue(resultSet.next());
+ assertEquals(3, resultSet.getInt(1));
+ assertEquals(3, resultSet.getInt(2));
+ assertEquals(2, resultSet.getInt(3));
+
+ assertFalse(resultSet.next());
+ }
+
+ statement.execute("flush");
+ try (ResultSet resultSet =
+ statement.executeQuery("select count(s1), count(s2), count(s3) from sg")) {
+
+ assertTrue(resultSet.next());
+ assertEquals(3, resultSet.getInt(1));
+ assertEquals(3, resultSet.getInt(2));
+ assertEquals(2, resultSet.getInt(3));
+
+ assertFalse(resultSet.next());
+ }
+ }
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/aligned/IoTDBInsertAlignedValues3IT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/aligned/IoTDBInsertAlignedValues3IT.java
new file mode 100644
index 0000000..d7c031d
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/aligned/IoTDBInsertAlignedValues3IT.java
@@ -0,0 +1,124 @@
+/*
+ * 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.relational.it.db.it.aligned;
+
+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.apache.iotdb.itbase.env.BaseEnv;
+
+import org.junit.After;
+import org.junit.Before;
+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;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+public class IoTDBInsertAlignedValues3IT {
+
+ @Before
+ public void setUp() throws Exception {
+ EnvFactory.getEnv()
+ .getConfig()
+ .getCommonConfig()
+ .setAutoCreateSchemaEnabled(true)
+ .setMaxNumberOfPointsInPage(4);
+ EnvFactory.getEnv().initClusterEnvironment();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ @Test
+ public void testInsertAlignedWithEmptyPage2() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("create database lz");
+ statement.execute("use \"lz\"");
+ statement.execute(
+ "create table dev (id1 string id, s1 int32 measurement, s2 int32 measurement, s3 int32 measurement)");
+ for (int i = 0; i < 100; i++) {
+ if (i >= 49) {
+ statement.addBatch(
+ "insert into dev(id1,time,s1,s2,s3) values("
+ + "GPS"
+ + ","
+ + i
+ + ","
+ + i
+ + ","
+ + i
+ + ","
+ + i
+ + ")");
+ } else {
+ statement.addBatch(
+ "insert into root.lz.dev.GPS(id1,time,s1,s2) values("
+ + "GPS"
+ + ","
+ + i
+ + ","
+ + i
+ + ","
+ + i
+ + ")");
+ }
+ }
+ statement.executeBatch();
+ statement.execute("flush");
+ int rowCount = 0;
+ try (ResultSet resultSet = statement.executeQuery("select s3 from dev")) {
+ while (resultSet.next()) {
+ assertEquals(rowCount + 49, resultSet.getInt(2));
+ rowCount++;
+ }
+ assertEquals(51, rowCount);
+ }
+
+ try (ResultSet resultSet = statement.executeQuery("select s2 from dev")) {
+ rowCount = 0;
+ while (resultSet.next()) {
+ assertEquals(rowCount, resultSet.getInt(2));
+ rowCount++;
+ }
+ assertEquals(100, rowCount);
+ }
+
+ try (ResultSet resultSet = statement.executeQuery("select s1 from dev")) {
+ rowCount = 0;
+ while (resultSet.next()) {
+ assertEquals(rowCount, resultSet.getInt(2));
+ rowCount++;
+ }
+ assertEquals(100, rowCount);
+ }
+ }
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/aligned/IoTDBInsertAlignedValues4IT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/aligned/IoTDBInsertAlignedValues4IT.java
new file mode 100644
index 0000000..aa6b4e2
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/aligned/IoTDBInsertAlignedValues4IT.java
@@ -0,0 +1,79 @@
+/*
+ * 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.relational.it.db.it.aligned;
+
+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.apache.iotdb.itbase.env.BaseEnv;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import static org.junit.Assert.fail;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+public class IoTDBInsertAlignedValues4IT {
+
+ @Before
+ public void setUp() throws Exception {
+ EnvFactory.getEnv()
+ .getConfig()
+ .getCommonConfig()
+ .setAutoCreateSchemaEnabled(true)
+ .setPrimitiveArraySize(2);
+ EnvFactory.getEnv().initClusterEnvironment();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ @Test
+ public void testExtendTextColumn() {
+
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("create database test");
+ statement.execute("use \"test\"");
+ statement.execute(
+ "create table sg (id1 string id, s1 string measurement, s2 string measurement)");
+ statement.execute("insert into sg(id1,time,s1,s2) values('d1',1,'test','test')");
+ statement.execute("insert into sg(id1,time,s1,s2) values('d1',2,'test','test')");
+ statement.execute("insert into sg(id1,time,s1,s2) values('d1',3,'test','test')");
+ statement.execute("insert into sg(id1,time,s1,s2) values('d1',4,'test','test')");
+ statement.execute("insert into sg(id1,time,s1,s3) values('d1',5,'test','test')");
+ statement.execute("insert into sg(id1,time,s1,s2) values('d1',6,'test','test')");
+ statement.execute("flush");
+ statement.execute("insert into sg(id1,time,s1,s3) values('d1',7,'test','test')");
+ fail();
+ } catch (SQLException ignored) {
+ }
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/aligned/IoTDBInsertAlignedValuesIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/aligned/IoTDBInsertAlignedValuesIT.java
new file mode 100644
index 0000000..b81dd97
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/aligned/IoTDBInsertAlignedValuesIT.java
@@ -0,0 +1,436 @@
+/*
+ * 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.relational.it.db.it.aligned;
+
+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.apache.iotdb.itbase.env.BaseEnv;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+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.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+public class IoTDBInsertAlignedValuesIT {
+
+ @Before
+ public void setUp() throws Exception {
+ EnvFactory.getEnv().getConfig().getCommonConfig().setAutoCreateSchemaEnabled(true);
+ EnvFactory.getEnv().initClusterEnvironment();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ @Test
+ public void testInsertAlignedValues() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.addBatch("create database t1");
+ statement.addBatch("use \"t1\"");
+ statement.addBatch(
+ "create table wf01 (id1 string id, status int32 measurement, temperature float measurement)");
+ statement.addBatch(
+ "insert into wf01(id1, time, status, temperature) values ('wt01', 4000, true, 17.1)");
+ statement.addBatch(
+ "insert into wf01(id1, time, status, temperature) values ('wt01', 5000, true, 20.1)");
+ statement.addBatch(
+ "insert into wf01(id1, time, status, temperature) values ('wt01', 6000, true, 22)");
+ statement.executeBatch();
+
+ try (ResultSet resultSet = statement.executeQuery("select time, status from wf01")) {
+ assertTrue(resultSet.next());
+ assertTrue(resultSet.getBoolean(2));
+ assertTrue(resultSet.next());
+ assertTrue(resultSet.getBoolean(2));
+ assertTrue(resultSet.next());
+ assertTrue(resultSet.getBoolean(2));
+ assertFalse(resultSet.next());
+ }
+
+ try (ResultSet resultSet =
+ statement.executeQuery("select time, status, temperature from wf01")) {
+
+ assertTrue(resultSet.next());
+ assertEquals(4000, resultSet.getLong(1));
+ assertTrue(resultSet.getBoolean(2));
+ assertEquals(17.1, resultSet.getDouble(3), 0.1);
+
+ assertTrue(resultSet.next());
+ assertEquals(5000, resultSet.getLong(1));
+ assertTrue(resultSet.getBoolean(2));
+ assertEquals(20.1, resultSet.getDouble(3), 0.1);
+
+ assertTrue(resultSet.next());
+ assertEquals(6000, resultSet.getLong(1));
+ assertTrue(resultSet.getBoolean(2));
+ assertEquals(22, resultSet.getDouble(3), 0.1);
+
+ assertFalse(resultSet.next());
+ }
+ }
+ }
+
+ @Test
+ public void testInsertAlignedNullableValues() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+
+ statement.addBatch("create database t1");
+ statement.addBatch("use \"t1\"");
+ statement.addBatch(
+ "create table wf01 (id1 string id, status boolean measurement, temperature float measurement)");
+ statement.addBatch(
+ "insert into wf01(id1, time, status, temperature) values ('wt01', 4000, true, 17.1)");
+ statement.addBatch("insert into wf01(id1, time, status) values ('wt01', 5000, true)");
+ statement.addBatch("insert into wf01(id1, time, temperature) values ('wt01', 6000, 22)");
+ statement.executeBatch();
+
+ try (ResultSet resultSet = statement.executeQuery("select status from wf01")) {
+ assertTrue(resultSet.next());
+ assertTrue(resultSet.getBoolean(2));
+ assertTrue(resultSet.next());
+ assertTrue(resultSet.getBoolean(2));
+ assertFalse(resultSet.next());
+ }
+
+ try (ResultSet resultSet =
+ statement.executeQuery("select time, status, temperature from wf01")) {
+
+ assertTrue(resultSet.next());
+ assertEquals(4000, resultSet.getLong(1));
+ assertTrue(resultSet.getBoolean(2));
+ assertEquals(17.1, resultSet.getDouble(3), 0.1);
+
+ assertTrue(resultSet.next());
+ assertEquals(5000, resultSet.getLong(1));
+ assertTrue(resultSet.getBoolean(2));
+ assertNull(resultSet.getObject(3));
+
+ assertTrue(resultSet.next());
+ assertEquals(6000, resultSet.getLong(1));
+ assertNull(resultSet.getObject(2));
+ assertEquals(22.0d, resultSet.getObject(3));
+
+ assertFalse(resultSet.next());
+ }
+ }
+ }
+
+ @Test
+ public void testUpdatingAlignedValues() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.addBatch("create database t1");
+ statement.addBatch("use \"t1\"");
+ statement.addBatch(
+ "create table wf01 (id1 string id, status boolean measurement, temperature float measurement)");
+ statement.addBatch(
+ "insert into wf01(id1, time, status, temperature) values ('wt01', 4000, true, 17.1)");
+ statement.addBatch("insert into wf01(id1, time, status) values ('wt01', 5000, true)");
+ statement.addBatch("insert into wf01(id1, time, temperature)values ('wt01', 5000, 20.1)");
+ statement.addBatch("insert into wf01(id1, time, temperature)values ('wt01', 6000, 22)");
+ statement.executeBatch();
+
+ try (ResultSet resultSet = statement.executeQuery("select time, status from wf01")) {
+ assertTrue(resultSet.next());
+ assertTrue(resultSet.getBoolean(2));
+ assertTrue(resultSet.next());
+ assertTrue(resultSet.getBoolean(2));
+ assertFalse(resultSet.next());
+ }
+
+ try (ResultSet resultSet =
+ statement.executeQuery("select time, status, temperature from wf01")) {
+
+ assertTrue(resultSet.next());
+ assertEquals(4000, resultSet.getLong(1));
+ assertTrue(resultSet.getBoolean(2));
+ assertEquals(17.1, resultSet.getDouble(3), 0.1);
+
+ assertTrue(resultSet.next());
+ assertEquals(5000, resultSet.getLong(1));
+ assertTrue(resultSet.getBoolean(2));
+ assertEquals(20.1, resultSet.getDouble(3), 0.1);
+
+ assertTrue(resultSet.next());
+ assertEquals(6000, resultSet.getLong(1));
+ assertNull(resultSet.getObject(2));
+ assertEquals(22.0d, resultSet.getObject(3));
+
+ assertFalse(resultSet.next());
+ }
+
+ statement.execute("flush");
+ try (ResultSet resultSet = statement.executeQuery("select time, status from wf01")) {
+ assertTrue(resultSet.next());
+ assertTrue(resultSet.getBoolean(2));
+ assertTrue(resultSet.next());
+ assertTrue(resultSet.getBoolean(2));
+ assertFalse(resultSet.next());
+ }
+
+ try (ResultSet resultSet =
+ statement.executeQuery("select time, status, temperature from wf01")) {
+
+ assertTrue(resultSet.next());
+ assertEquals(4000, resultSet.getLong(1));
+ assertTrue(resultSet.getBoolean(2));
+ assertEquals(17.1, resultSet.getDouble(3), 0.1);
+
+ assertTrue(resultSet.next());
+ assertEquals(5000, resultSet.getLong(1));
+ assertTrue(resultSet.getBoolean(2));
+ assertEquals(20.1, resultSet.getDouble(3), 0.1);
+
+ assertTrue(resultSet.next());
+ assertEquals(6000, resultSet.getLong(1));
+ assertNull(resultSet.getObject(2));
+ assertEquals(22.0d, resultSet.getObject(3));
+
+ assertFalse(resultSet.next());
+ }
+ }
+ }
+
+ @Test
+ public void testInsertAlignedValuesWithSameTimestamp() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.addBatch("create database test");
+ statement.addBatch("use \"test\"");
+ statement.addBatch(
+ "create table sg (ids string id, s2 int32 measurement, s1 int32 measurement)");
+ statement.addBatch("insert into sg(id1,time,s2) values('d1',1,2)");
+ statement.addBatch("insert into sg(id1,time,s1) values('d1',1,2)");
+ statement.executeBatch();
+
+ try (ResultSet resultSet = statement.executeQuery("select time, s1, s2 from sg")) {
+
+ assertTrue(resultSet.next());
+ assertEquals(1, resultSet.getLong(1));
+ assertEquals(2.0d, resultSet.getObject(2));
+ assertEquals(2.0d, resultSet.getObject(3));
+
+ assertFalse(resultSet.next());
+ }
+
+ statement.execute("flush");
+ try (ResultSet resultSet = statement.executeQuery("select time, s1, s2 from sg")) {
+
+ assertTrue(resultSet.next());
+ assertEquals(1, resultSet.getLong(1));
+ assertEquals(2.0d, resultSet.getObject(2));
+ assertEquals(2.0d, resultSet.getObject(3));
+
+ assertFalse(resultSet.next());
+ }
+ }
+ }
+
+ @Test
+ public void testInsertWithWrongMeasurementNum1() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("create database t1");
+ statement.execute("use \"t1\"");
+ statement.execute(
+ "create table wf01 (id1 string id, status int32, temperature int32 measurement)");
+ statement.execute(
+ "insert into wf01(id1, time, status, temperature) values('wt01', 11000, 100)");
+ fail();
+ } catch (SQLException e) {
+ assertTrue(e.getMessage().contains("failed"));
+ }
+ }
+
+ @Test
+ public void testInsertWithWrongMeasurementNum2() {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("create database t1");
+ statement.execute("use \"t1\"");
+ statement.execute(
+ "create table wf01 (id1 string id, status int32, temperature int32 measurement)");
+ statement.execute(
+ "insert into wf01(id1, time, status, temperature) values('wt01', 11000, 100, 300, 400)");
+ fail();
+ } catch (SQLException e) {
+ assertTrue(e.getMessage(), e.getMessage().contains("failed"));
+ }
+ }
+
+ @Test(expected = Exception.class)
+ public void testInsertWithWrongType() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("create database lz");
+ statement.execute("use \"lz\"");
+ statement.execute(
+ "create table dev (id1 string id, latitude int32 measurement, longitude int32 measurement)");
+ statement.execute("insert into dev(id1,time,latitude,longitude) values('GPS', 1,1.3,6.7)");
+ fail();
+ }
+ }
+
+ @Test
+ @Ignore // TODO: delete
+ public void testInsertAlignedTimeseriesWithoutAligned() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(
+ "CREATE ALIGNED TIMESERIES root.lz.dev.GPS2(latitude INT32 encoding=PLAIN compressor=SNAPPY, longitude INT32 encoding=PLAIN compressor=SNAPPY) ");
+ statement.execute("insert into root.lz.dev.GPS2(time,latitude,longitude) values(1,123,456)");
+ // it's supported.
+ }
+ }
+
+ @Test
+ public void testInsertTimeseriesWithUnMatchedAlignedType() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("create ALIGNED timeseries root.db.d_aligned(s01 INT64 encoding=RLE)");
+ statement.execute("insert into root.db.d_aligned(time, s01) aligned values (4000, 123)");
+ statement.execute("insert into root.db.d_aligned(time, s01) values (5000, 456)");
+ statement.execute("create timeseries root.db.d_not_aligned.s01 INT64 encoding=RLE");
+ statement.execute("insert into root.db.d_not_aligned(time, s01) values (4000, 987)");
+ statement.execute("insert into root.db.d_not_aligned(time, s01) aligned values (5000, 654)");
+
+ try (ResultSet resultSet = statement.executeQuery("select s01 from root.db.d_aligned")) {
+ assertTrue(resultSet.next());
+ assertEquals(4000, resultSet.getLong(1));
+ assertEquals(123, resultSet.getLong(2));
+
+ assertTrue(resultSet.next());
+ assertEquals(5000, resultSet.getLong(1));
+ assertEquals(456, resultSet.getLong(2));
+
+ assertFalse(resultSet.next());
+ }
+
+ try (ResultSet resultSet = statement.executeQuery("select s01 from root.db.d_not_aligned")) {
+ assertTrue(resultSet.next());
+ assertEquals(4000, resultSet.getLong(1));
+ assertEquals(987, resultSet.getLong(2));
+
+ assertTrue(resultSet.next());
+ assertEquals(5000, resultSet.getLong(1));
+ assertEquals(654, resultSet.getLong(2));
+
+ assertFalse(resultSet.next());
+ }
+ }
+ }
+
+ @Test
+ @Ignore // TODO: delete
+ public void testInsertNonAlignedTimeseriesWithAligned() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("CREATE TIMESERIES root.lz.dev.GPS3.latitude with datatype=INT32");
+ statement.execute("CREATE TIMESERIES root.lz.dev.GPS3.longitude with datatype=INT32");
+ statement.execute(
+ "insert into root.lz.dev.GPS3(time,latitude,longitude) aligned values(1,123,456)");
+ // it's supported.
+ }
+ }
+
+ @Test
+ @Ignore // TODO: delete
+ public void testInsertAlignedValuesWithThreeLevelPath() throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("insert into root.sg_device(time, status) aligned values (4000, true)");
+
+ try (ResultSet resultSet = statement.executeQuery("select ** from root")) {
+ assertTrue(resultSet.next());
+ assertTrue(resultSet.getBoolean(2));
+ assertFalse(resultSet.next());
+ }
+ }
+ }
+
+ @Test
+ public void testInsertWithDuplicatedMeasurements() {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("create database t1");
+ statement.execute("use \"t1\"");
+ statement.execute("create table wf01(id1 string id, s3 boolean measurement, status int32)");
+ statement.execute(
+ "insert into wf01(id1, time, s3, status, status) values('wt01', 100, true, 20.1, 20.2)");
+ fail();
+ } catch (SQLException e) {
+ assertTrue(
+ e.getMessage(),
+ e.getMessage().contains("Insertion contains duplicated measurement: status"));
+ }
+ }
+
+ @Test
+ public void testInsertMultiRows() {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("create database test");
+ statement.execute("use \"test\"");
+ statement.execute(
+ "create table sg1 (id1 string id, s1 int32 measurement, s2 int32 measurement)");
+ statement.execute(
+ "insert into sg1(id1, time, s1, s2) values('d1', 10, 2, 2), ('d1', 11, 3, '3'), ('d1', 12,12.11,false)");
+ fail();
+ } catch (SQLException e) {
+ assertTrue(e.getMessage(), e.getMessage().contains("data type is not consistent"));
+ }
+ }
+
+ @Test
+ public void testInsertLargeNumber() {
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute("create database test");
+ statement.execute("use \"test\"");
+ statement.execute(
+ "create table sg1 (id1 string id, s98 int64 measurement, s99 int64 measurement)");
+ statement.execute(
+ "insert into sg1(id1, time, s98, s99) values('d1', 10, 2, 271840880000000000000000)");
+ } catch (SQLException e) {
+ fail();
+ }
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/schema/IoTDBAutoCreateSchemaIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/schema/IoTDBAutoCreateSchemaIT.java
new file mode 100644
index 0000000..69a1148
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/schema/IoTDBAutoCreateSchemaIT.java
@@ -0,0 +1,274 @@
+/*
+ * 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.relational.it.db.it.schema;
+
+import org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant;
+import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.itbase.category.ClusterIT;
+import org.apache.iotdb.itbase.category.LocalStandaloneIT;
+import org.apache.iotdb.itbase.constant.TestConstant;
+import org.apache.iotdb.util.AbstractSchemaIT;
+
+import org.apache.tsfile.enums.TSDataType;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.Parameterized;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Notice that, all test begins with "IoTDB" is integration test. All test which will start the
+ * IoTDB server should be defined as integration test.
+ */
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+@Ignore // TODO: delete this test
+public class IoTDBAutoCreateSchemaIT extends AbstractSchemaIT {
+
+ public IoTDBAutoCreateSchemaIT(SchemaTestMode schemaTestMode) {
+ super(schemaTestMode);
+ }
+
+ @Parameterized.BeforeParam
+ public static void before() throws Exception {
+ setUpEnvironment();
+ EnvFactory.getEnv().initClusterEnvironment();
+ }
+
+ @Parameterized.AfterParam
+ public static void after() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ tearDownEnvironment();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ clearSchema();
+ }
+
+ /** create timeseries without setting database */
+ @Test
+ public void createTimeseriesTest() throws ClassNotFoundException {
+ String[] sqls = {
+ "CREATE TIMESERIES root.sg0.d1.s2 WITH DATATYPE=INT32,ENCODING=RLE",
+ "INSERT INTO root.sg0.d1(timestamp,s2) values(1,123)",
+ };
+ executeSQL(sqls);
+ }
+
+ /** insert data when database has been set but timeseries hasn't been created */
+ @Test
+ public void insertTest1() throws ClassNotFoundException {
+ String[] sqls = {
+ "CREATE DATABASE root.sg0",
+ "INSERT INTO root.sg0.d1(timestamp,s2) values(1,123.123)",
+ "INSERT INTO root.sg0.d1(timestamp,s3) values(1,\"abc\")",
+ };
+ executeSQL(sqls);
+ }
+
+ /** insert data when database hasn't been set and timeseries hasn't been created */
+ @Test
+ public void insertTest2() throws ClassNotFoundException {
+ String[] sqls = {
+ "INSERT INTO root.sg0.d1(timestamp,s2) values(1,\"abc\")",
+ "INSERT INTO root.sg0.d2(timestamp,s3) values(1,123.123)",
+ "INSERT INTO root.sg0.d2(timestamp,s4) values(1,123456)",
+ };
+ executeSQL(sqls);
+ }
+
+ private void executeSQL(String[] sqls) throws ClassNotFoundException {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ String result = "";
+ Long now_start = 0L;
+ boolean cmp = false;
+
+ for (String sql : sqls) {
+ if (cmp) {
+ Assert.assertEquals(sql, result);
+ cmp = false;
+ } else if (sql.equals("SHOW TIMESERIES")) {
+ DatabaseMetaData data = connection.getMetaData();
+ result = data.toString();
+ cmp = true;
+ } else {
+ if (sql.contains("NOW()") && now_start == 0L) {
+ now_start = System.currentTimeMillis();
+ }
+
+ if (sql.split(" ")[0].equals("SELECT")) {
+ ResultSet resultSet = statement.executeQuery(sql);
+ ResultSetMetaData metaData = resultSet.getMetaData();
+ int count = metaData.getColumnCount();
+ String[] column = new String[count];
+ for (int i = 0; i < count; i++) {
+ column[i] = metaData.getColumnName(i + 1);
+ }
+ result = "";
+ while (resultSet.next()) {
+ for (int i = 1; i <= count; i++) {
+ if (now_start > 0L && column[i - 1].equals(TestConstant.TIMESTAMP_STR)) {
+ String timestr = resultSet.getString(i);
+ Long tn = Long.valueOf(timestr);
+ Long now = System.currentTimeMillis();
+ if (tn >= now_start && tn <= now) {
+ timestr = "NOW()";
+ }
+ result += timestr + ',';
+ } else {
+ result += resultSet.getString(i) + ',';
+ }
+ }
+ result += '\n';
+ }
+ cmp = true;
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * test if automatically creating a time series will cause the database with same name to
+ * disappear
+ */
+ @Test
+ public void testInsertAutoCreate2() throws Exception {
+ String storageGroup = "root.sg2.a.b.c";
+ String timeSeriesPrefix = "root.sg2.a.b";
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(String.format("CREATE DATABASE %s", storageGroup));
+ try {
+ statement.execute(
+ String.format("INSERT INTO %s(timestamp, c) values(123, \"aabb\")", timeSeriesPrefix));
+ } catch (SQLException ignored) {
+ }
+
+ // ensure that current database in cache is right.
+ InsertAutoCreate2Tool(statement, storageGroup, timeSeriesPrefix);
+ }
+ // todo restart test
+ // EnvironmentUtils.stopDaemon();
+ // setUp();
+ //
+ // // ensure that database in cache is right after recovering.
+ // InsertAutoCreate2Tool(storageGroup, timeSeriesPrefix);
+ }
+
+ private void InsertAutoCreate2Tool(
+ Statement statement, String storageGroup, String timeSeriesPrefix) throws SQLException {
+ Set<String> resultList = new HashSet<>();
+ try (ResultSet resultSet = statement.executeQuery("show timeseries")) {
+ while (resultSet.next()) {
+ String str = resultSet.getString(ColumnHeaderConstant.TIMESERIES);
+ resultList.add(str);
+ }
+ }
+ Assert.assertFalse(resultList.contains(timeSeriesPrefix + "c"));
+
+ resultList.clear();
+ try (ResultSet resultSet = statement.executeQuery("show databases")) {
+ while (resultSet.next()) {
+ resultList.add(resultSet.getString(ColumnHeaderConstant.DATABASE));
+ }
+ }
+ Assert.assertTrue(resultList.contains(storageGroup));
+ }
+
+ /**
+ * insert data when database hasn't been set, timeseries hasn't been created and have null values
+ */
+ @Test
+ public void testInsertAutoCreate3() throws SQLException {
+ String[] sqls = {
+ "INSERT INTO root.sg0.d3(timestamp,s1) values(1,null)",
+ "INSERT INTO root.sg0.d3(timestamp,s1,s2) values(1,null,2)",
+ };
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ for (String sql : sqls) {
+ try {
+ statement.execute(sql);
+ } catch (SQLException e) {
+ Assert.assertTrue(e.getMessage().contains("Path [root.sg0.d3.s1] does not exist"));
+ }
+ }
+ }
+ }
+
+ /**
+ * insert data when database hasn't been set, timeseries hasn't been created and have null values
+ */
+ @Test
+ public void testAutoCreateDataType() throws SQLException {
+ String SQL =
+ "INSERT INTO root.sg0.d1(time,s1,s2,s3,s4,s5,s6) values(1,true,1,now(),X'cafe',\"string\",\"2024-01-01\")";
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(SQL);
+ ResultSet resultSet = statement.executeQuery("show timeseries");
+ while (resultSet.next()) {
+ switch (resultSet.getString(ColumnHeaderConstant.TIMESERIES)) {
+ case "root.sg0.d1.s1":
+ assertEquals(
+ TSDataType.BOOLEAN.toString(), resultSet.getString(ColumnHeaderConstant.DATATYPE));
+ break;
+ case "root.sg0.d1.s2":
+ assertEquals(
+ TSDataType.DOUBLE.toString(), resultSet.getString(ColumnHeaderConstant.DATATYPE));
+ break;
+ case "root.sg0.d1.s3":
+ assertEquals(
+ TSDataType.INT64.toString(), resultSet.getString(ColumnHeaderConstant.DATATYPE));
+ break;
+ case "root.sg0.d1.s4":
+ assertEquals(
+ TSDataType.BLOB.toString(), resultSet.getString(ColumnHeaderConstant.DATATYPE));
+ break;
+ case "root.sg0.d1.s5":
+ assertEquals(
+ TSDataType.TEXT.toString(), resultSet.getString(ColumnHeaderConstant.DATATYPE));
+ break;
+ case "root.sg0.d1.s6":
+ assertEquals(
+ TSDataType.TEXT.toString(), resultSet.getString(ColumnHeaderConstant.DATATYPE));
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/schema/IoTDBCreateAlignedTimeseriesIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/schema/IoTDBCreateAlignedTimeseriesIT.java
new file mode 100644
index 0000000..a6b7450
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/schema/IoTDBCreateAlignedTimeseriesIT.java
@@ -0,0 +1,144 @@
+/*
+ * 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.relational.it.db.it.schema;
+
+import org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant;
+import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.itbase.category.ClusterIT;
+import org.apache.iotdb.itbase.category.LocalStandaloneIT;
+import org.apache.iotdb.util.AbstractSchemaIT;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.Parameterized;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+/**
+ * Notice that, all test begins with "IoTDB" is integration test. All test which will start the
+ * IoTDB server should be defined as integration test.
+ */
+public class IoTDBCreateAlignedTimeseriesIT extends AbstractSchemaIT {
+
+ public IoTDBCreateAlignedTimeseriesIT(SchemaTestMode schemaTestMode) {
+ super(schemaTestMode);
+ }
+
+ @Parameterized.BeforeParam
+ public static void before() throws Exception {
+ setUpEnvironment();
+ EnvFactory.getEnv().initClusterEnvironment();
+ }
+
+ @Parameterized.AfterParam
+ public static void after() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ tearDownEnvironment();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ clearSchema();
+ }
+
+ @Test
+ @Category({LocalStandaloneIT.class, ClusterIT.class})
+ public void testCreateAlignedTimeseries() throws Exception {
+ String[] timeSeriesArray =
+ new String[] {
+ "root.sg1.d1.vector1.s1,FLOAT,PLAIN,UNCOMPRESSED", "root.sg1.d1.vector1.s2,INT64,RLE,LZ4"
+ };
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("CREATE DATABASE root.sg1");
+ try {
+ statement.execute(
+ "CREATE ALIGNED TIMESERIES root.sg1.d1.vector1(s1 FLOAT encoding=PLAIN compressor=UNCOMPRESSED,s2 INT64 encoding=RLE)");
+ } catch (SQLException ignored) {
+ }
+
+ // ensure that current database in cache is right.
+ assertTimeseriesEquals(timeSeriesArray);
+ }
+ // todo test restart
+ // EnvironmentUtils.stopDaemon();
+ // setUp();
+ //
+ // // ensure database in cache is right after recovering.
+ // assertTimeseriesEquals(timeSeriesArray);
+ }
+
+ @Test
+ public void testCreateAlignedTimeseriesWithDeletion() throws Exception {
+ String[] timeSeriesArray =
+ new String[] {
+ "root.sg1.d1.vector1.s1,DOUBLE,PLAIN,SNAPPY", "root.sg1.d1.vector1.s2,INT64,RLE,LZ4"
+ };
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("CREATE DATABASE root.sg1");
+ try {
+ statement.execute(
+ "CREATE ALIGNED TIMESERIES root.sg1.d1.vector1(s1 FLOAT encoding=PLAIN compressor=UNCOMPRESSED,s2 INT64 encoding=RLE)");
+ statement.execute("DELETE TIMESERIES root.sg1.d1.vector1.s1");
+ statement.execute(
+ "CREATE ALIGNED TIMESERIES root.sg1.d1.vector1(s1 DOUBLE encoding=PLAIN compressor=SNAPPY)");
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ // ensure that current database in cache is right.
+ assertTimeseriesEquals(timeSeriesArray);
+
+ // todo
+ // EnvironmentUtils.stopDaemon();
+ // setUp();
+
+ // ensure database in cache is right after recovering.
+ assertTimeseriesEquals(timeSeriesArray);
+ }
+
+ private void assertTimeseriesEquals(String[] timeSeriesArray) throws SQLException {
+
+ int count = 0;
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("SHOW TIMESERIES")) {
+ while (resultSet.next()) {
+ String ActualResult =
+ resultSet.getString(ColumnHeaderConstant.TIMESERIES)
+ + ","
+ + resultSet.getString(ColumnHeaderConstant.DATATYPE)
+ + ","
+ + resultSet.getString(ColumnHeaderConstant.ENCODING)
+ + ","
+ + resultSet.getString(ColumnHeaderConstant.COMPRESSION);
+ Assert.assertEquals(timeSeriesArray[count], ActualResult);
+ count++;
+ }
+ }
+ Assert.assertEquals(timeSeriesArray.length, count);
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/schema/IoTDBCreateStorageGroupIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/schema/IoTDBCreateStorageGroupIT.java
new file mode 100644
index 0000000..761ff14
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/schema/IoTDBCreateStorageGroupIT.java
@@ -0,0 +1,155 @@
+/*
+ * 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.relational.it.db.it.schema;
+
+import org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant;
+import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.itbase.category.ClusterIT;
+import org.apache.iotdb.itbase.category.LocalStandaloneIT;
+import org.apache.iotdb.itbase.env.BaseEnv;
+import org.apache.iotdb.rpc.TSStatusCode;
+import org.apache.iotdb.util.AbstractSchemaIT;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.Parameterized;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.junit.Assert.fail;
+
+/**
+ * Notice that, all test begins with "IoTDB" is integration test. All test which will start the
+ * IoTDB server should be defined as integration test.
+ */
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+public class IoTDBCreateStorageGroupIT extends AbstractSchemaIT {
+
+ public IoTDBCreateStorageGroupIT(SchemaTestMode schemaTestMode) {
+ super(schemaTestMode);
+ }
+
+ @Parameterized.BeforeParam
+ public static void before() throws Exception {
+ setUpEnvironment();
+ EnvFactory.getEnv().initClusterEnvironment();
+ }
+
+ @Parameterized.AfterParam
+ public static void after() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ tearDownEnvironment();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ clearSchema();
+ }
+
+ /** The test creates three databases */
+ @Test
+ public void testCreateStorageGroup() throws Exception {
+ String[] storageGroups = {"sg1", "sg2", "sg3"};
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ for (String storageGroup : storageGroups) {
+ statement.execute(String.format("create database %s", storageGroup));
+ }
+
+ // ensure that current StorageGroup in cache is right.
+ createStorageGroupTool(statement, storageGroups);
+ }
+ // todo test restart
+ // EnvironmentUtils.stopDaemon();
+ // setUp();
+ //
+ // // ensure StorageGroup in cache is right after recovering.
+ // createStorageGroupTool(storageGroups);
+ }
+
+ private void createStorageGroupTool(Statement statement, String[] storageGroups)
+ throws SQLException {
+
+ List<String> resultList = new ArrayList<>();
+ try (ResultSet resultSet = statement.executeQuery("SHOW DATABASES")) {
+ while (resultSet.next()) {
+ String storageGroupPath = resultSet.getString(ColumnHeaderConstant.DATABASE);
+ resultList.add(storageGroupPath);
+ }
+ }
+ Assert.assertEquals(3, resultList.size());
+
+ resultList = resultList.stream().sorted().collect(Collectors.toList());
+
+ Assert.assertEquals(storageGroups[0], resultList.get(0));
+ Assert.assertEquals(storageGroups[1], resultList.get(1));
+ Assert.assertEquals(storageGroups[2], resultList.get(2));
+ }
+
+ /** Test creating a database that path is an existence database */
+ @Test
+ public void testCreateExistStorageGroup1() throws Exception {
+ String storageGroup = "sg";
+
+ try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+ Statement statement = connection.createStatement()) {
+ statement.execute(String.format("CREATE DATABASE %s", storageGroup));
+
+ try {
+ statement.execute(String.format("create database %s", storageGroup));
+ fail();
+ } catch (SQLException e) {
+ Assert.assertEquals(
+ TSStatusCode.DATABASE_ALREADY_EXISTS.getStatusCode() + ": Database sg already exists",
+ e.getMessage());
+ }
+ }
+ }
+
+ /** Test the parent node has been set as a database */
+ @Test
+ @Ignore // TODO: delete this test
+ public void testCreateExistStorageGroup2() throws Exception {
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("create database root.sg");
+
+ try {
+ statement.execute("create database root.sg.`device`");
+ fail();
+ } catch (SQLException e) {
+ Assert.assertEquals(
+ TSStatusCode.DATABASE_ALREADY_EXISTS.getStatusCode()
+ + ": root.sg has already been created as database",
+ e.getMessage());
+ }
+ }
+ }
+}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/schema/IoTDBCreateTimeseriesIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/schema/IoTDBCreateTimeseriesIT.java
new file mode 100644
index 0000000..6468938
--- /dev/null
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/schema/IoTDBCreateTimeseriesIT.java
@@ -0,0 +1,300 @@
+/*
+ * 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.relational.it.db.it.schema;
+
+import org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant;
+import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.itbase.category.ClusterIT;
+import org.apache.iotdb.itbase.category.LocalStandaloneIT;
+import org.apache.iotdb.util.AbstractSchemaIT;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.Parameterized;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.fail;
+
+/**
+ * Notice that, all test begins with "IoTDB" is integration test. All test which will start the
+ * IoTDB server should be defined as integration test.
+ */
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+@Ignore // TODO: delete this test
+public class IoTDBCreateTimeseriesIT extends AbstractSchemaIT {
+
+ public IoTDBCreateTimeseriesIT(SchemaTestMode schemaTestMode) {
+ super(schemaTestMode);
+ }
+
+ @Parameterized.BeforeParam
+ public static void before() throws Exception {
+ setUpEnvironment();
+ EnvFactory.getEnv().initClusterEnvironment();
+ }
+
+ @Parameterized.AfterParam
+ public static void after() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ tearDownEnvironment();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ clearSchema();
+ }
+
+ /** Test if creating a time series will cause the database with same name to disappear */
+ @Test
+ public void testCreateTimeseries() throws Exception {
+ String storageGroup = "root.sg1.a.b.c";
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(String.format("CREATE DATABASE %s", storageGroup));
+ statement.execute(
+ String.format(
+ "create timeseries %s with datatype=INT64, encoding=PLAIN, compression=SNAPPY",
+ storageGroup));
+
+ } catch (Exception ignored) {
+ }
+
+ // ensure that current database in cache is right.
+ createTimeSeriesTool(storageGroup);
+ }
+
+ private void createTimeSeriesTool(String storageGroup) throws SQLException {
+ Set<String> resultList = new HashSet<>();
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("show timeseries")) {
+ while (resultSet.next()) {
+ String str = resultSet.getString(ColumnHeaderConstant.TIMESERIES);
+ resultList.add(str);
+ }
+ }
+ Assert.assertFalse(resultList.contains(storageGroup));
+ resultList.clear();
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("SHOW DATABASES")) {
+ while (resultSet.next()) {
+ String res = resultSet.getString(ColumnHeaderConstant.DATABASE);
+ resultList.add(res);
+ }
+ }
+ Assert.assertTrue(resultList.contains(storageGroup));
+ }
+
+ @Test
+ public void testCreateTimeseriesWithSpecialCharacter() throws Exception {
+ try (Connection connection = EnvFactory.getEnv().getConnection()) {
+ try (Statement statement = connection.createStatement()) {
+ statement.execute(
+ String.format(
+ "create timeseries %s with datatype=INT64, encoding=PLAIN, compression=SNAPPY",
+ "root.sg.d.a\".\"b"));
+ fail();
+ } catch (SQLException ignored) {
+ }
+ try (Statement statement = connection.createStatement()) {
+ statement.execute(
+ String.format(
+ "create timeseries %s with datatype=INT64, encoding=PLAIN, compression=SNAPPY",
+ "root.sg.d.a“(Φ)”b"));
+ fail();
+ } catch (SQLException ignored) {
+ }
+ try (Statement statement = connection.createStatement()) {
+ statement.execute(
+ String.format(
+ "create timeseries %s with datatype=INT64, encoding=PLAIN, compression=SNAPPY",
+ "root.sg.d.a>b"));
+ fail();
+ } catch (SQLException ignored) {
+ }
+ }
+
+ String[] timeSeriesArray = {
+ "root.sg.d.`a.b`", "root.sg.d.`a“(Φ)”b`", "root.sg.d.`a>b`", "root.sg.d.`0e38`"
+ };
+ String[] timeSeriesResArray = {
+ "root.sg.d.`a.b`", "root.sg.d.`a“(Φ)”b`", "root.sg.d.`a>b`", "root.sg.d.`0e38`",
+ };
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ for (String timeSeries : timeSeriesArray) {
+ statement.execute(
+ String.format(
+ "create timeseries %s with datatype=INT64, encoding=PLAIN, compression=SNAPPY",
+ timeSeries));
+ }
+ }
+
+ // ensure that current timeseries in cache is right.
+ createTimeSeriesWithSpecialCharacterTool(timeSeriesResArray);
+ }
+
+ private void createTimeSeriesWithSpecialCharacterTool(String[] timeSeriesArray)
+ throws SQLException {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("count timeseries root.sg.**")) {
+ while (resultSet.next()) {
+ long count = resultSet.getLong(1);
+ Assert.assertEquals(timeSeriesArray.length, count);
+ }
+ }
+ }
+
+ @Test
+ public void testCreateTimeSeriesWithWrongAttribute() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(
+ String.format("create timeseries %s with datatype=INT64, datatype = test", "root.sg.a"));
+ fail();
+ } catch (SQLException ignored) {
+ }
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(String.format("create timeseries %s with encoding=plain", "root.sg.a"));
+ fail();
+ } catch (SQLException ignored) {
+ }
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(
+ String.format(
+ "create timeseries %s with encoding=plain, compressor=snappy", "root.sg.a"));
+ fail();
+ } catch (SQLException ignored) {
+ }
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(
+ String.format("create timeseries %s with datatype=float, encoding=plan", "root.sg.a"));
+ fail();
+ } catch (SQLException ignored) {
+ }
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(
+ String.format("create timeseries %s with datatype=INT64, encoding=test", "root.sg.a"));
+ fail();
+ } catch (SQLException ignored) {
+ }
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(
+ String.format(
+ "create timeseries %s with datatype=INT64, encoding=test, compression=test",
+ "root.sg.a"));
+ fail();
+ } catch (SQLException ignored) {
+ }
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(
+ String.format("create timeseries %s with datatype=INT64,compression=test", "root.sg.a"));
+ fail();
+ } catch (SQLException ignored) {
+ }
+
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute(
+ String.format(
+ "create timeseries %s with datatype=INT64, encoding=PLAIN, compression=test",
+ "root.sg.a"));
+ fail();
+ } catch (SQLException ignored) {
+ }
+ }
+
+ @Test
+ public void testQueryDataFromTimeSeriesWithoutData() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("create timeseries root.sg2.d.s1 with datatype=INT64");
+ } catch (SQLException ignored) {
+ fail();
+ }
+ int cnt = 0;
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement();
+ ResultSet resultSet = statement.executeQuery("select s1 from root.sg2.d")) {
+ while (resultSet.next()) {
+ cnt++;
+ }
+ } catch (SQLException e) {
+ fail();
+ }
+ Assert.assertEquals(0, cnt);
+ }
+
+ @Test
+ public void testIllegalInput() {
+ try (Connection connection = EnvFactory.getEnv().getConnection();
+ Statement statement = connection.createStatement()) {
+ statement.execute("create timeseries root.sg2.d.s1 with datatype=INT64");
+ assertThrows(
+ "Unsupported datatype: UNKNOWN",
+ SQLException.class,
+ () -> statement.execute("create timeseries root.sg2.d.s1 with datatype=UNKNOWN"));
+ assertThrows(
+ "Unsupported datatype: VECTOR",
+ SQLException.class,
+ () -> statement.execute("create timeseries root.sg2.d.s1 with datatype=VECTOR"));
+ assertThrows(
+ "Unsupported datatype: YES",
+ SQLException.class,
+ () -> statement.execute("create timeseries root.sg2.d.s1 with datatype=YES"));
+ assertThrows(
+ "Unsupported datatype: UNKNOWN",
+ SQLException.class,
+ () -> statement.execute("create device template t1 (s1 UNKNOWN, s2 boolean)"));
+ assertThrows(
+ "Unsupported datatype: VECTOR",
+ SQLException.class,
+ () -> statement.execute("create device template t1 (s1 VECTOR, s2 boolean)"));
+ } catch (SQLException ignored) {
+ fail();
+ }
+ }
+}