This is an automated email from the ASF dual-hosted git repository.
rong pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new feddaa31b9 [IOTDB-3041] Add code example of using jdbc/session
interface after updating syntax convention (#6145)
feddaa31b9 is described below
commit feddaa31b988582fcb7b6634fb95aa2d8513a110
Author: Liao Lanyu <[email protected]>
AuthorDate: Tue Jun 7 09:48:58 2022 +0800
[IOTDB-3041] Add code example of using jdbc/session interface after
updating syntax convention (#6145)
---
docs/UserGuide/API/Programming-Java-Native-API.md | 8 +-
docs/UserGuide/Reference/Syntax-Conventions.md | 2 +-
.../UserGuide/API/Programming-Java-Native-API.md | 8 +-
docs/zh/UserGuide/Reference/Syntax-Conventions.md | 2 +-
.../iotdb/SyntaxConventionRelatedExample.java | 161 +++++++++++++++++++++
.../iotdb/SyntaxConventionRelatedExample.java | 145 +++++++++++++++++++
6 files changed, 314 insertions(+), 12 deletions(-)
diff --git a/docs/UserGuide/API/Programming-Java-Native-API.md
b/docs/UserGuide/API/Programming-Java-Native-API.md
index 699c60eb44..247af53d08 100644
--- a/docs/UserGuide/API/Programming-Java-Native-API.md
+++ b/docs/UserGuide/API/Programming-Java-Native-API.md
@@ -45,15 +45,13 @@ In root directory:
</dependencies>
```
-## Syntax Description
+## Syntax Convention
- **IoTDB-SQL interface:** The input SQL parameter needs to conform to the
[syntax conventions](../Reference/Syntax-Conventions.md) and be escaped for
JAVA strings. For example, you need to add a backslash before the
double-quotes. (That is: after JAVA escaping, it is consistent with the SQL
statement executed on the command line.)
- **Other interfaces:**
- - The node names in path or path prefix as parameter:
- - The node names which should be escaped by backticks (`) in the SQL
statement, and escaping is not required here.
- - The node names enclosed in single or double quotes still need to be
enclosed in single or double quotes and must be escaped for JAVA strings.
- - For the `checkTimeseriesExists` interface, since the IoTDB-SQL interface
is called internally, the time-series pathname must be consistent with the SQL
syntax conventions and be escaped for JAVA strings.
+ - The node names in path or path prefix as parameter: The node names which
should be escaped by backticks (`) in the SQL statement, escaping is required
here.
- Identifiers (such as template names) as parameters: The identifiers which
should be escaped by backticks (`) in the SQL statement, and escaping is not
required here.
+- **Code example for syntax convention could be found at:**
`example/session/src/main/java/org/apache/iotdb/SyntaxConventionRelatedExample.java`
## Native APIs
diff --git a/docs/UserGuide/Reference/Syntax-Conventions.md
b/docs/UserGuide/Reference/Syntax-Conventions.md
index cb00ab9706..183abaeb90 100644
--- a/docs/UserGuide/Reference/Syntax-Conventions.md
+++ b/docs/UserGuide/Reference/Syntax-Conventions.md
@@ -601,7 +601,7 @@ Keywords are words that have significance in SQL. Keywords
can be used as an ide
## Session、TsFile API
-When using the Session and TsFile APIs, if the method you call requires
parameters such as measurement, device, storage group, path in the form of
String, **please ensure that the parameters passed in the input string is the
same as when using the SQL statement**, here are some examples to help you
understand.
+When using the Session and TsFile APIs, if the method you call requires
parameters such as measurement, device, storage group, path in the form of
String, **please ensure that the parameters passed in the input string is the
same as when using the SQL statement**, here are some examples to help you
understand. Code example could be found at:
`example/session/src/main/java/org/apache/iotdb/SyntaxConventionRelatedExample.java`
1. Take creating a time series createTimeseries as an example:
diff --git a/docs/zh/UserGuide/API/Programming-Java-Native-API.md
b/docs/zh/UserGuide/API/Programming-Java-Native-API.md
index 4eb1492d7f..94c1ed40f2 100644
--- a/docs/zh/UserGuide/API/Programming-Java-Native-API.md
+++ b/docs/zh/UserGuide/API/Programming-Java-Native-API.md
@@ -52,11 +52,9 @@ mvn clean install -pl session -am -Dmaven.test.skip=true
- 对于 IoTDB-SQL 接口:传入的 SQL 参数需要符合 [语法规范](../Reference/Syntax-Conventions.md)
,并且针对 JAVA 字符串进行反转义,如双引号前需要加反斜杠。(即:经 JAVA 转义之后与命令行执行的 SQL 语句一致。)
- 对于其他接口:
- - 经参数传入的路径或路径前缀中的节点:
- - 在 SQL 语句中需要使用反引号(`)进行转义的,此处均不需要进行转义。
- - 使用单引号或双引号括起的节点,仍需要使用单引号或双引号括起,并且要针对 JAVA 字符串进行反转义。
- - 对于 `checkTimeseriesExists` 接口,由于内部调用了 IoTDB-SQL 接口,因此需要和 SQL
语法规范保持一致,并且针对 JAVA 字符串进行反转义。
- - 经参数传入的标识符(如模板名):在 SQL 语句中需要使用反引号(`)进行转义的,此处均不需要进行转义。
+ - 经参数传入的路径或路径前缀中的节点: 在 SQL 语句中需要使用反引号(`)进行转义的,此处均需要进行转义。
+ - 经参数传入的标识符(如模板名):在 SQL 语句中需要使用反引号(`)进行转义的,均可以不用进行转义。
+ -
语法说明相关代码示例可以参考:`example/session/src/main/java/org/apache/iotdb/SyntaxConventionRelatedExample.java`
## 基本接口说明
diff --git a/docs/zh/UserGuide/Reference/Syntax-Conventions.md
b/docs/zh/UserGuide/Reference/Syntax-Conventions.md
index 1bdfda42e0..5e64344bef 100644
--- a/docs/zh/UserGuide/Reference/Syntax-Conventions.md
+++ b/docs/zh/UserGuide/Reference/Syntax-Conventions.md
@@ -603,7 +603,7 @@ CREATE PIPE my_pipe TO my_iotdb FROM
## Session、TsFile API
-在使用Session、TsFIle
API时,如果您调用的方法需要以字符串形式传入物理量(measurement)、设备(device)、存储组(storage
group)、路径(path)等参数,**请保证所传入字符串与使用 SQL 语句时的写法一致**,下面是一些帮助您理解的例子。
+在使用Session、TsFIle
API时,如果您调用的方法需要以字符串形式传入物理量(measurement)、设备(device)、存储组(storage
group)、路径(path)等参数,**请保证所传入字符串与使用 SQL
语句时的写法一致**,下面是一些帮助您理解的例子。具体代码示例可以参考:`example/session/src/main/java/org/apache/iotdb/SyntaxConventionRelatedExample.java`
1. 以创建时间序列 createTimeseries 为例:
diff --git
a/example/jdbc/src/main/java/org/apache/iotdb/SyntaxConventionRelatedExample.java
b/example/jdbc/src/main/java/org/apache/iotdb/SyntaxConventionRelatedExample.java
new file mode 100644
index 0000000000..5858b49554
--- /dev/null
+++
b/example/jdbc/src/main/java/org/apache/iotdb/SyntaxConventionRelatedExample.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;
+
+import org.apache.iotdb.jdbc.IoTDBSQLException;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+
+public class SyntaxConventionRelatedExample {
+ /**
+ * if you want to create a time series named root.sg1.select, a possible SQL
statement would be
+ * like: create timeseries root.sg1.select with datatype=FLOAT, encoding=RLE
As described before,
+ * when using session API, path is represented using String. The path should
be written as
+ * "root.sg1.select".
+ */
+ private static final String ROOT_SG1_KEYWORD_EXAMPLE = "root.sg1.select";
+
+ /**
+ * if you want to create a time series named root.sg1.111, a possible SQL
statement would be like:
+ * create timeseries root.sg1.`111` with datatype=FLOAT, encoding=RLE The
path should be written
+ * as "root.sg1.`111`".
+ */
+ private static final String ROOT_SG1_DIGITS_EXAMPLE = "root.sg1.`111`";
+
+ /**
+ * if you want to create a time series named root.sg1.`a"b'c``, a possible
SQL statement would be
+ * like: create timeseries root.sg1.`a"b'c``` with datatype=FLOAT,
encoding=RLE The path should be
+ * written as "root.sg1.`a"b`c```".
+ */
+ private static final String ROOT_SG1_SPECIAL_CHARACTER_EXAMPLE =
"root.sg1.`a\"b'c```";
+
+ /**
+ * if you want to create a time series named root.sg1.a, a possible SQL
statement would be like:
+ * create timeseries root.sg1.a with datatype=FLOAT, encoding=RLE The path
should be written as
+ * "root.sg1.a".
+ */
+ private static final String ROOT_SG1_NORMAL_NODE_EXAMPLE = "root.sg1.a";
+
+ private static final String DEVICE = "root.sg1";
+
+ public static void main(String[] args) throws ClassNotFoundException,
SQLException {
+ Class.forName("org.apache.iotdb.jdbc.IoTDBDriver");
+ try (Connection connection =
+ DriverManager.getConnection(
+ "jdbc:iotdb://127.0.0.1:6667?version=V_0_13", "root", "root");
+ Statement statement = connection.createStatement()) {
+
+ // set JDBC fetchSize
+ statement.setFetchSize(10000);
+
+ // create time series
+ try {
+ statement.execute(String.format("SET STORAGE GROUP TO %s", DEVICE));
+ statement.execute(
+ String.format(
+ "CREATE TIMESERIES %s WITH DATATYPE=INT64, ENCODING=RLE,
COMPRESSOR=SNAPPY",
+ ROOT_SG1_DIGITS_EXAMPLE));
+ statement.execute(
+ String.format(
+ "CREATE TIMESERIES %s WITH DATATYPE=INT64, ENCODING=RLE,
COMPRESSOR=SNAPPY",
+ ROOT_SG1_KEYWORD_EXAMPLE));
+ statement.execute(
+ String.format(
+ "CREATE TIMESERIES %s WITH DATATYPE=INT64, ENCODING=RLE,
COMPRESSOR=SNAPPY",
+ ROOT_SG1_NORMAL_NODE_EXAMPLE));
+ statement.execute(
+ String.format(
+ "CREATE TIMESERIES %s WITH DATATYPE=INT64, ENCODING=RLE,
COMPRESSOR=SNAPPY",
+ ROOT_SG1_SPECIAL_CHARACTER_EXAMPLE));
+ } catch (IoTDBSQLException e) {
+ System.out.println(e.getMessage());
+ }
+
+ // show timeseries
+ ResultSet resultSet = statement.executeQuery("show timeseries
root.sg1.*");
+ List<String> timeseriesList = new ArrayList<>();
+ while (resultSet.next()) {
+ timeseriesList.add(resultSet.getString("timeseries"));
+ }
+ for (String path : timeseriesList) {
+ for (int i = 0; i <= 10; i++) {
+ statement.addBatch(prepareInsertStatement(i, path));
+ }
+ }
+ statement.executeBatch();
+ statement.clearBatch();
+
+ resultSet = statement.executeQuery("select ** from root.sg1 where time
<= 10");
+ outputResult(resultSet);
+ for (String path : timeseriesList) {
+ // For example, for timeseires root.sg1.`111`, sensor is 111, as
described in syntax
+ // convention, it should be written as `111` in SQL
+ // in resultSet of "show timeseries", result is root.sg1.`111`, which
means you need not to
+ // worry about dealing with backquotes yourself.
+ resultSet =
+ statement.executeQuery(String.format("select %s from root.sg1",
removeDevice(path)));
+ outputResult(resultSet);
+ }
+ } catch (IoTDBSQLException e) {
+ System.out.println(e.getMessage());
+ }
+ }
+
+ private static void outputResult(ResultSet resultSet) throws SQLException {
+ if (resultSet != null) {
+ System.out.println("--------------------------");
+ final ResultSetMetaData metaData = resultSet.getMetaData();
+ final int columnCount = metaData.getColumnCount();
+ for (int i = 0; i < columnCount; i++) {
+ System.out.print(metaData.getColumnLabel(i + 1) + " ");
+ }
+ System.out.println();
+ while (resultSet.next()) {
+ for (int i = 1; ; i++) {
+ System.out.print(resultSet.getString(i));
+ if (i < columnCount) {
+ System.out.print(", ");
+ } else {
+ System.out.println();
+ break;
+ }
+ }
+ }
+ System.out.println("--------------------------\n");
+ }
+ }
+
+ private static String prepareInsertStatement(int time, String path) {
+ // remove device root.sg1
+ path = removeDevice(path);
+ return String.format(
+ "insert into root.sg1(timestamp, %s) values(" + time + "," + 1 + ")",
path);
+ }
+
+ private static String removeDevice(String path) {
+ return path.substring(DEVICE.length() + 1);
+ }
+}
diff --git
a/example/session/src/main/java/org/apache/iotdb/SyntaxConventionRelatedExample.java
b/example/session/src/main/java/org/apache/iotdb/SyntaxConventionRelatedExample.java
new file mode 100644
index 0000000000..362702f76a
--- /dev/null
+++
b/example/session/src/main/java/org/apache/iotdb/SyntaxConventionRelatedExample.java
@@ -0,0 +1,145 @@
+/*
+ * 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;
+
+import org.apache.iotdb.rpc.IoTDBConnectionException;
+import org.apache.iotdb.rpc.StatementExecutionException;
+import org.apache.iotdb.rpc.TSStatusCode;
+import org.apache.iotdb.session.Session;
+import org.apache.iotdb.session.SessionDataSet;
+import org.apache.iotdb.session.util.Version;
+import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * When using session API, measurement, device, storage group and path are
represented by String.
+ * The content of the String should be the same as what you would write in a
SQL statement. This
+ * class is an example to help you understand better.
+ */
+public class SyntaxConventionRelatedExample {
+ private static Session session;
+ private static final String LOCAL_HOST = "127.0.0.1";
+ /**
+ * if you want to create a time series named root.sg1.select, a possible SQL
statement would be
+ * like: create timeseries root.sg1.select with datatype=FLOAT, encoding=RLE
As described before,
+ * when using session API, path is represented using String. The path should
be written as
+ * "root.sg1.select".
+ */
+ private static final String ROOT_SG1_KEYWORD_EXAMPLE = "root.sg1.select";
+
+ /**
+ * if you want to create a time series named root.sg1.111, a possible SQL
statement would be like:
+ * create timeseries root.sg1.`111` with datatype=FLOAT, encoding=RLE The
path should be written
+ * as "root.sg1.`111`".
+ */
+ private static final String ROOT_SG1_DIGITS_EXAMPLE = "root.sg1.`111`";
+
+ /**
+ * if you want to create a time series named root.sg1.`a"b'c``, a possible
SQL statement would be
+ * like: create timeseries root.sg1.`a"b'c``` with datatype=FLOAT,
encoding=RLE The path should be
+ * written as "root.sg1.`a"b`c```".
+ */
+ private static final String ROOT_SG1_SPECIAL_CHARACTER_EXAMPLE =
"root.sg1.`a\"b'c```";
+
+ /**
+ * if you want to create a time series named root.sg1.a, a possible SQL
statement would be like:
+ * create timeseries root.sg1.a with datatype=FLOAT, encoding=RLE The path
should be written as
+ * "root.sg1.a".
+ */
+ private static final String ROOT_SG1_NORMAL_NODE_EXAMPLE = "root.sg1.a";
+
+ public static void main(String[] args)
+ throws IoTDBConnectionException, StatementExecutionException {
+ session =
+ new Session.Builder()
+ .host(LOCAL_HOST)
+ .port(6667)
+ .username("root")
+ .password("root")
+ .version(Version.V_0_13)
+ .build();
+ session.open(false);
+
+ // set session fetchSize
+ session.setFetchSize(10000);
+
+ try {
+ session.setStorageGroup("root.sg1");
+ } catch (StatementExecutionException e) {
+ if (e.getStatusCode() !=
TSStatusCode.PATH_ALREADY_EXIST_ERROR.getStatusCode()) {
+ throw e;
+ }
+ }
+
+ // createTimeSeries
+ createTimeSeries();
+ SessionDataSet dataSet = session.executeQueryStatement("show timeseries
root.sg1.*");
+ // the expected paths would be:
+ // [root.sg1.select, root.sg1.`111`, root.sg1.`a"b'c```, root.sg1.a]
+ // You could see that time series in dataSet are exactly the same as
+ // the initial String you used as path. Node names consist of digits or
contain special
+ // characters are quoted with ``, both in SQL statement and in header of
result dataset.
+ // It's convenient that you can use the result of show timeseries as input
parameter directly
+ // for other
+ // session APIs such as insertRecord or executeRawDataQuery.
+ List<String> paths = new ArrayList<>();
+ while (dataSet.hasNext()) {
+ paths.add(dataSet.next().getFields().get(0).toString());
+ }
+
+ long startTime = 1L;
+ long endTime = 100L;
+
+ try (SessionDataSet dataSet1 = session.executeRawDataQuery(paths,
startTime, endTime)) {
+
+ System.out.println(dataSet1.getColumnNames());
+ dataSet1.setFetchSize(1024);
+ while (dataSet1.hasNext()) {
+ System.out.println(dataSet1.next());
+ }
+ }
+ }
+
+ private static void createTimeSeries()
+ throws IoTDBConnectionException, StatementExecutionException {
+ if (!session.checkTimeseriesExists(ROOT_SG1_KEYWORD_EXAMPLE)) {
+ session.createTimeseries(
+ ROOT_SG1_KEYWORD_EXAMPLE, TSDataType.FLOAT, TSEncoding.RLE,
CompressionType.SNAPPY);
+ }
+ if (!session.checkTimeseriesExists(ROOT_SG1_DIGITS_EXAMPLE)) {
+ session.createTimeseries(
+ ROOT_SG1_DIGITS_EXAMPLE, TSDataType.FLOAT, TSEncoding.RLE,
CompressionType.SNAPPY);
+ }
+ if (!session.checkTimeseriesExists(ROOT_SG1_SPECIAL_CHARACTER_EXAMPLE)) {
+ session.createTimeseries(
+ ROOT_SG1_SPECIAL_CHARACTER_EXAMPLE,
+ TSDataType.FLOAT,
+ TSEncoding.RLE,
+ CompressionType.SNAPPY);
+ }
+ if (!session.checkTimeseriesExists(ROOT_SG1_NORMAL_NODE_EXAMPLE)) {
+ session.createTimeseries(
+ ROOT_SG1_NORMAL_NODE_EXAMPLE, TSDataType.FLOAT, TSEncoding.RLE,
CompressionType.SNAPPY);
+ }
+ }
+}