This is an automated email from the ASF dual-hosted git repository. CritasWang pushed a commit to branch docs/rust-client-sdk in repository https://gitbox.apache.org/repos/asf/iotdb-docs.git
commit 11550eb162059c4098041431147ccf2bd6507370 Author: CritasWang <[email protected]> AuthorDate: Mon Jul 20 14:14:21 2026 +0800 docs: refresh Rust client docs for the official apache/iotdb-client-rust SDK - Rewrite the tree-model Rust API page (latest + Master/Tree, en + zh): the old page documented hand-generating Thrift stubs; it now covers the official SDK (installation, quick start, session pool, TLS/compression). - Add the table-model Rust API page (latest-Table + Master/Table, en + zh). - Add the Rust entry to the V2.0.x Table sidebars (en + zh); the Tree sidebars already had it. --- src/.vuepress/sidebar/V2.0.x/en-Table.ts | 1 + src/.vuepress/sidebar/V2.0.x/zh-Table.ts | 1 + .../API/Programming-Rust-Native-API_apache.md | 134 ++++++++++ .../Master/Tree/API/Programming-Rust-Native-API.md | 267 +++++++++----------- .../API/Programming-Rust-Native-API_apache.md | 134 ++++++++++ .../latest/API/Programming-Rust-Native-API.md | 267 +++++++++----------- .../API/Programming-Rust-Native-API_apache.md | 133 ++++++++++ .../Master/Tree/API/Programming-Rust-Native-API.md | 277 +++++++++------------ .../API/Programming-Rust-Native-API_apache.md | 133 ++++++++++ .../latest/API/Programming-Rust-Native-API.md | 277 +++++++++------------ 10 files changed, 1026 insertions(+), 598 deletions(-) diff --git a/src/.vuepress/sidebar/V2.0.x/en-Table.ts b/src/.vuepress/sidebar/V2.0.x/en-Table.ts index bf72d970..4312ed68 100644 --- a/src/.vuepress/sidebar/V2.0.x/en-Table.ts +++ b/src/.vuepress/sidebar/V2.0.x/en-Table.ts @@ -184,6 +184,7 @@ export const enSidebar = { { text: 'C++ Native API', link: 'Programming-Cpp-Native-API_apache' }, { text: 'GO Native API', link: 'Programming-Go-Native-API_apache' }, { text: 'C# Native API', link: 'Programming-CSharp-Native-API_apache' }, + { text: 'Rust Native API', link: 'Programming-Rust-Native-API_apache' }, { text: 'JDBC', link: 'Programming-JDBC_apache' }, { text: 'MQTT Protocol', link: 'Programming-MQTT_apache' }, { text: 'RESTAPI V1 ', link: 'RestAPI-V1_apache' }, diff --git a/src/.vuepress/sidebar/V2.0.x/zh-Table.ts b/src/.vuepress/sidebar/V2.0.x/zh-Table.ts index 3a0364a2..41897721 100644 --- a/src/.vuepress/sidebar/V2.0.x/zh-Table.ts +++ b/src/.vuepress/sidebar/V2.0.x/zh-Table.ts @@ -183,6 +183,7 @@ export const zhSidebar = { { text: 'C++原生接口', link: 'Programming-Cpp-Native-API_apache' }, { text: 'GO原生接口', link: 'Programming-Go-Native-API_apache' }, { text: 'C#原生接口', link: 'Programming-CSharp-Native-API_apache' }, + { text: 'Rust原生接口', link: 'Programming-Rust-Native-API_apache' }, { text: 'JDBC', link: 'Programming-JDBC_apache' }, { text: 'MQTT协议', link: 'Programming-MQTT_apache' }, { text: 'RESTAPI V1 ', link: 'RestServiceV1_apache' }, diff --git a/src/UserGuide/Master/Table/API/Programming-Rust-Native-API_apache.md b/src/UserGuide/Master/Table/API/Programming-Rust-Native-API_apache.md new file mode 100644 index 00000000..fa8252ff --- /dev/null +++ b/src/UserGuide/Master/Table/API/Programming-Rust-Native-API_apache.md @@ -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. + +--> + +# Rust Native API + +Apache IoTDB provides an official Rust client SDK: [apache/iotdb-client-rust](https://github.com/apache/iotdb-client-rust). It speaks the Thrift RPC protocol (default port 6667). This document covers the **table model** (`TableSession` / `TableSessionPool`, relational SQL dialect); the tree model is documented separately. + +## 1. Requirements + +- Rust 1.75+ +- Apache IoTDB 2.x — see [COMPATIBILITY.md](https://github.com/apache/iotdb-client-rust/blob/main/COMPATIBILITY.md) for the full server version matrix + +## 2. Installation + +Once published to crates.io: + +```toml +[dependencies] +iotdb-client-rust = "0.1" +``` + +Until then, use a git dependency: + +```toml +[dependencies] +iotdb-client = { git = "https://github.com/apache/iotdb-client-rust" } +``` + +The import name is `iotdb_client` in both cases. + +## 3. Quick start + +```rust +use iotdb_client::{ColumnCategory, Result, TSDataType, TableSession, Tablet, Value}; + +fn main() -> Result<()> { + let mut session = TableSession::builder() + .node_urls(&["127.0.0.1:6667"])? + .username("root") + .password("root") + .build()?; + + session.execute_non_query("CREATE DATABASE IF NOT EXISTS demo")?; + session.execute_non_query("USE demo")?; + session.execute_non_query( + "CREATE TABLE IF NOT EXISTS sensors (device_id STRING TAG, temperature DOUBLE FIELD)", + )?; + + // Column-major tablet write. columnCategories must NOT include TIME — + // the time column is implicit. + let mut tablet = Tablet::new_table( + "sensors", + vec!["device_id".into(), "temperature".into()], + vec![TSDataType::String, TSDataType::Double], + vec![ColumnCategory::Tag, ColumnCategory::Field], + )?; + tablet.add_row( + 1_720_000_000_000, + vec![ + Some(Value::String("dev-1".into())), + Some(Value::Double(21.5)), + ], + )?; + session.insert(&tablet)?; + + // Query with row iteration; the dataset borrows the session until dropped. + { + let mut dataset = + session.execute_query("SELECT time, device_id, temperature FROM sensors")?; + while let Some(row) = dataset.next_row()? { + println!("{:?}", row.values); + } + } + + session.execute_non_query("DROP DATABASE demo")?; + session.close() +} +``` + +## 4. Session pool + +`TableSessionPool` is the thread-safe pool variant for concurrent workloads; `acquire()` returns an RAII guard that releases the session back to the pool on drop. See the runnable [`session_pool` example](https://github.com/apache/iotdb-client-rust/blob/main/examples/session_pool.rs). + +## 5. TLS & RPC compression + +**RPC compression** (the Thrift compact protocol) must match the server setting `dn_rpc_thrift_compression_enable` (default `false`): + +```rust +let mut session = TableSession::builder() + .node_urls(&["127.0.0.1:6667"])? + .enable_rpc_compression(true) + .build()?; +``` + +**TLS** is behind the `tls` cargo feature: + +```toml +iotdb-client-rust = { version = "0.1", features = ["tls"] } +``` + +```rust +let mut session = TableSession::builder() + .node_urls(&["127.0.0.1:6667"])? + .use_ssl(true) + .ca_cert_path("ca.pem") + .build()?; +``` + +## 6. Examples + +Full runnable examples live in the repository's [`examples/`](https://github.com/apache/iotdb-client-rust/tree/main/examples) directory: + +```sh +cargo run --example table_session +cargo run --example session_pool +``` diff --git a/src/UserGuide/Master/Tree/API/Programming-Rust-Native-API.md b/src/UserGuide/Master/Tree/API/Programming-Rust-Native-API.md index f3fcacf4..e4a8b0a0 100644 --- a/src/UserGuide/Master/Tree/API/Programming-Rust-Native-API.md +++ b/src/UserGuide/Master/Tree/API/Programming-Rust-Native-API.md @@ -21,168 +21,147 @@ # Rust Native API -IoTDB uses Thrift as a cross language RPC framework, so access to IoTDB can be achieved through the interface provided by Thrift. -This document will introduce how to generate a native Rust interface that can access IoTDB. +Apache IoTDB provides an official Rust client SDK: [apache/iotdb-client-rust](https://github.com/apache/iotdb-client-rust). It speaks the Thrift RPC protocol (default port 6667) and supports both IoTDB data models: -## 1. Dependents +- **Tree model** — `Session` / `SessionPool`: device/timeseries paths (`root.sg.d1.s1`), covered in this document +- **Table model** — `TableSession` / `TableSessionPool`: relational SQL dialect - * JDK >= 1.8 - * Rust >= 1.0.0 - * thrift 0.14.1 - * Linux、Macos or like unix - * Windows+bash +## 1. Requirements -Thrift (0.14.1 or higher) must be installed to compile Thrift files into Rust code. The following is the official installation tutorial, and in the end, you should receive a Thrift executable file. +- Rust 1.75+ +- Apache IoTDB 2.x — see [COMPATIBILITY.md](https://github.com/apache/iotdb-client-rust/blob/main/COMPATIBILITY.md) for the full server version matrix -``` -http://thrift.apache.org/docs/install/ -``` +## 2. Installation -## 2. Compile the Thrift library and generate the Rust native interface - -1. Find the `pom.xml` file in the root directory of the IoTDB source code folder. -2. Open the `pom.xml` file and find the following content: - ```xml - <execution> - <id>generate-thrift-sources-python</id> - <phase>generate-sources</phase> - <goals> - <goal>compile</goal> - </goals> - <configuration> - <generator>py</generator> - <outputDirectory>${project.build.directory}/generated-sources-python/</outputDirectory> - </configuration> - </execution> - ``` -3. Duplicate this block and change the `id`, `generator` and `outputDirectory` to this: - ```xml - <execution> - <id>generate-thrift-sources-rust</id> - <phase>generate-sources</phase> - <goals> - <goal>compile</goal> - </goals> - <configuration> - <generator>rs</generator> - <outputDirectory>${project.build.directory}/generated-sources-rust/</outputDirectory> - </configuration> - </execution> - ``` -4. In the root directory of the IoTDB source code folder,run `mvn clean generate-sources`. - -This command will automatically delete the files in `iotdb/iotdb-protocol/thrift/target` and `iotdb/iotdb-protocol/thrift-commons/target`, and repopulate the folder with the newly generated files. -The newly generated Rust sources will be located in `iotdb/iotdb-protocol/thrift/target/generated-sources-rust` in the various modules of the `iotdb-protocol` module. - -## 3. Using the Rust native interface - -Copy `iotdb/iotdb-protocol/thrift/target/generated-sources-rust/` and `iotdb/iotdb-protocol/thrift-commons/target/generated-sources-rust/` into your project。 - -## 4. RPC interface +Once published to crates.io: +```toml +[dependencies] +iotdb-client-rust = "0.1" ``` -// open a session -TSOpenSessionResp openSession(1:TSOpenSessionReq req); - -// close a session -TSStatus closeSession(1:TSCloseSessionReq req); - -// run an SQL statement in batch -TSExecuteStatementResp executeStatement(1:TSExecuteStatementReq req); - -// execute SQL statement in batch -TSStatus executeBatchStatement(1:TSExecuteBatchStatementReq req); - -// execute query SQL statement -TSExecuteStatementResp executeQueryStatement(1:TSExecuteStatementReq req); - -// execute insert, delete and update SQL statement -TSExecuteStatementResp executeUpdateStatement(1:TSExecuteStatementReq req); - -// fetch next query result -TSFetchResultsResp fetchResults(1:TSFetchResultsReq req) - -// fetch meta data -TSFetchMetadataResp fetchMetadata(1:TSFetchMetadataReq req) - -// cancel a query -TSStatus cancelOperation(1:TSCancelOperationReq req); - -// close a query dataset -TSStatus closeOperation(1:TSCloseOperationReq req); - -// get time zone -TSGetTimeZoneResp getTimeZone(1:i64 sessionId); - -// set time zone -TSStatus setTimeZone(1:TSSetTimeZoneReq req); - -// get server's properties -ServerProperties getProperties(); - -// CREATE DATABASE -TSStatus setStorageGroup(1:i64 sessionId, 2:string storageGroup); -// create timeseries -TSStatus createTimeseries(1:TSCreateTimeseriesReq req); +Until then, use a git dependency: -// create multi timeseries -TSStatus createMultiTimeseries(1:TSCreateMultiTimeseriesReq req); - -// delete timeseries -TSStatus deleteTimeseries(1:i64 sessionId, 2:list<string> path) - -// delete sttorage groups -TSStatus deleteStorageGroups(1:i64 sessionId, 2:list<string> storageGroup); - -// insert record -TSStatus insertRecord(1:TSInsertRecordReq req); - -// insert record in string format -TSStatus insertStringRecord(1:TSInsertStringRecordReq req); - -// insert tablet -TSStatus insertTablet(1:TSInsertTabletReq req); - -// insert tablets in batch -TSStatus insertTablets(1:TSInsertTabletsReq req); - -// insert records in batch -TSStatus insertRecords(1:TSInsertRecordsReq req); - -// insert records of one device -TSStatus insertRecordsOfOneDevice(1:TSInsertRecordsOfOneDeviceReq req); +```toml +[dependencies] +iotdb-client = { git = "https://github.com/apache/iotdb-client-rust" } +``` -// insert records in batch as string format -TSStatus insertStringRecords(1:TSInsertStringRecordsReq req); +The import name is `iotdb_client` in both cases. + +## 3. Quick start + +```rust +use iotdb_client::{Result, Session, SessionConfig, TSDataType, Tablet, Value}; + +fn main() -> Result<()> { + let config = SessionConfig::default().with_node_urls(&["127.0.0.1:6667"])?; + let mut session = Session::new(config); + session.open()?; + + session.execute_non_query("CREATE DATABASE root.demo")?; + session.execute_non_query( + "CREATE TIMESERIES root.demo.d1.temperature WITH DATATYPE=DOUBLE, ENCODING=PLAIN", + )?; + + // Batch write via a column-major tablet (nulls allowed). + let mut tablet = Tablet::new( + "root.demo.d1", + vec!["temperature".into()], + vec![TSDataType::Double], + )?; + tablet.add_row(1_720_000_000_000, vec![Some(Value::Double(21.5))])?; + tablet.add_row(1_720_000_001_000, vec![None])?; // null cell + session.insert_tablet(&tablet)?; + + // Or write a single row via insertRecord (aligned variants and + // multi-row insert_records / insert_records_of_one_device also exist). + session.insert_record( + "root.demo.d1", + 1_720_000_002_000, + vec!["temperature".into()], + &[Value::Double(22.0)], + false, // is_aligned + )?; + + // Query with row iteration; the dataset borrows the session until dropped. + { + let mut dataset = session.execute_query("SELECT temperature FROM root.demo.d1")?; + while let Some(row) = dataset.next_row()? { + println!("ts={:?} values={:?}", row.timestamp, row.values); + } + } + + session.execute_non_query("DELETE DATABASE root.demo")?; + session.close() +} +``` -// test the latency of innsert tablet,caution:no data will be inserted, only for test latency -TSStatus testInsertTablet(1:TSInsertTabletReq req); +## 4. Session pool + +`SessionPool` is a thread-safe pool for concurrent workloads. `acquire()` returns an RAII guard that releases the session back to the pool on drop: + +```rust +use std::sync::Arc; +use iotdb_client::{Result, SessionPool, SessionPoolConfig}; + +fn main() -> Result<()> { + let config = SessionPoolConfig { + max_size: 4, + ..SessionPoolConfig::default() + } + .with_node_urls(&["127.0.0.1:6667"])?; + let pool = Arc::new(SessionPool::new(config)?); + + let handles: Vec<_> = (0..4) + .map(|_| { + let pool = Arc::clone(&pool); + std::thread::spawn(move || -> Result<()> { + let mut session = pool.acquire()?; + session.execute_non_query("SHOW DATABASES")?; + Ok(()) + }) + }) + .collect(); + for handle in handles { + handle.join().expect("thread panicked")?; + } + + pool.close(); + Ok(()) +} +``` -// test the latency of innsert tablets,caution:no data will be inserted, only for test latency -TSStatus testInsertTablets(1:TSInsertTabletsReq req); +## 5. TLS & RPC compression -// test the latency of innsert record,caution:no data will be inserted, only for test latency -TSStatus testInsertRecord(1:TSInsertRecordReq req); +**RPC compression** (the Thrift compact protocol) must match the server setting `dn_rpc_thrift_compression_enable` (default `false`): -// test the latency of innsert record in string format,caution:no data will be inserted, only for test latency -TSStatus testInsertStringRecord(1:TSInsertStringRecordReq req); +```rust +let config = SessionConfig { enable_rpc_compression: true, ..Default::default() }; +``` -// test the latency of innsert records,caution:no data will be inserted, only for test latency -TSStatus testInsertRecords(1:TSInsertRecordsReq req); +**TLS** is behind the `tls` cargo feature: -// test the latency of innsert records of one device,caution:no data will be inserted, only for test latency -TSStatus testInsertRecordsOfOneDevice(1:TSInsertRecordsOfOneDeviceReq req); +```toml +iotdb-client-rust = { version = "0.1", features = ["tls"] } +``` -// test the latency of innsert records in string formate,caution:no data will be inserted, only for test latency -TSStatus testInsertStringRecords(1:TSInsertStringRecordsReq req); +```rust +let config = SessionConfig { + use_ssl: true, + ca_cert_path: Some("ca.pem".into()), // trust a private CA / self-signed cert + accept_invalid_certs: false, // true skips verification (tests only!) + domain_override: None, // SNI/validation hostname when connecting by IP + ..Default::default() +}; +``` -// delete data -TSStatus deleteData(1:TSDeleteDataReq req); +## 6. Examples -// execute raw data query -TSExecuteStatementResp executeRawDataQuery(1:TSRawDataQueryReq req); +Full runnable examples live in the repository's [`examples/`](https://github.com/apache/iotdb-client-rust/tree/main/examples) directory: -// request a statement id from server -i64 requestStatementId(1:i64 sessionId); +```sh +cargo run --example tree_session +cargo run --example table_session +cargo run --example session_pool ``` diff --git a/src/UserGuide/latest-Table/API/Programming-Rust-Native-API_apache.md b/src/UserGuide/latest-Table/API/Programming-Rust-Native-API_apache.md new file mode 100644 index 00000000..fa8252ff --- /dev/null +++ b/src/UserGuide/latest-Table/API/Programming-Rust-Native-API_apache.md @@ -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. + +--> + +# Rust Native API + +Apache IoTDB provides an official Rust client SDK: [apache/iotdb-client-rust](https://github.com/apache/iotdb-client-rust). It speaks the Thrift RPC protocol (default port 6667). This document covers the **table model** (`TableSession` / `TableSessionPool`, relational SQL dialect); the tree model is documented separately. + +## 1. Requirements + +- Rust 1.75+ +- Apache IoTDB 2.x — see [COMPATIBILITY.md](https://github.com/apache/iotdb-client-rust/blob/main/COMPATIBILITY.md) for the full server version matrix + +## 2. Installation + +Once published to crates.io: + +```toml +[dependencies] +iotdb-client-rust = "0.1" +``` + +Until then, use a git dependency: + +```toml +[dependencies] +iotdb-client = { git = "https://github.com/apache/iotdb-client-rust" } +``` + +The import name is `iotdb_client` in both cases. + +## 3. Quick start + +```rust +use iotdb_client::{ColumnCategory, Result, TSDataType, TableSession, Tablet, Value}; + +fn main() -> Result<()> { + let mut session = TableSession::builder() + .node_urls(&["127.0.0.1:6667"])? + .username("root") + .password("root") + .build()?; + + session.execute_non_query("CREATE DATABASE IF NOT EXISTS demo")?; + session.execute_non_query("USE demo")?; + session.execute_non_query( + "CREATE TABLE IF NOT EXISTS sensors (device_id STRING TAG, temperature DOUBLE FIELD)", + )?; + + // Column-major tablet write. columnCategories must NOT include TIME — + // the time column is implicit. + let mut tablet = Tablet::new_table( + "sensors", + vec!["device_id".into(), "temperature".into()], + vec![TSDataType::String, TSDataType::Double], + vec![ColumnCategory::Tag, ColumnCategory::Field], + )?; + tablet.add_row( + 1_720_000_000_000, + vec![ + Some(Value::String("dev-1".into())), + Some(Value::Double(21.5)), + ], + )?; + session.insert(&tablet)?; + + // Query with row iteration; the dataset borrows the session until dropped. + { + let mut dataset = + session.execute_query("SELECT time, device_id, temperature FROM sensors")?; + while let Some(row) = dataset.next_row()? { + println!("{:?}", row.values); + } + } + + session.execute_non_query("DROP DATABASE demo")?; + session.close() +} +``` + +## 4. Session pool + +`TableSessionPool` is the thread-safe pool variant for concurrent workloads; `acquire()` returns an RAII guard that releases the session back to the pool on drop. See the runnable [`session_pool` example](https://github.com/apache/iotdb-client-rust/blob/main/examples/session_pool.rs). + +## 5. TLS & RPC compression + +**RPC compression** (the Thrift compact protocol) must match the server setting `dn_rpc_thrift_compression_enable` (default `false`): + +```rust +let mut session = TableSession::builder() + .node_urls(&["127.0.0.1:6667"])? + .enable_rpc_compression(true) + .build()?; +``` + +**TLS** is behind the `tls` cargo feature: + +```toml +iotdb-client-rust = { version = "0.1", features = ["tls"] } +``` + +```rust +let mut session = TableSession::builder() + .node_urls(&["127.0.0.1:6667"])? + .use_ssl(true) + .ca_cert_path("ca.pem") + .build()?; +``` + +## 6. Examples + +Full runnable examples live in the repository's [`examples/`](https://github.com/apache/iotdb-client-rust/tree/main/examples) directory: + +```sh +cargo run --example table_session +cargo run --example session_pool +``` diff --git a/src/UserGuide/latest/API/Programming-Rust-Native-API.md b/src/UserGuide/latest/API/Programming-Rust-Native-API.md index f3fcacf4..e4a8b0a0 100644 --- a/src/UserGuide/latest/API/Programming-Rust-Native-API.md +++ b/src/UserGuide/latest/API/Programming-Rust-Native-API.md @@ -21,168 +21,147 @@ # Rust Native API -IoTDB uses Thrift as a cross language RPC framework, so access to IoTDB can be achieved through the interface provided by Thrift. -This document will introduce how to generate a native Rust interface that can access IoTDB. +Apache IoTDB provides an official Rust client SDK: [apache/iotdb-client-rust](https://github.com/apache/iotdb-client-rust). It speaks the Thrift RPC protocol (default port 6667) and supports both IoTDB data models: -## 1. Dependents +- **Tree model** — `Session` / `SessionPool`: device/timeseries paths (`root.sg.d1.s1`), covered in this document +- **Table model** — `TableSession` / `TableSessionPool`: relational SQL dialect - * JDK >= 1.8 - * Rust >= 1.0.0 - * thrift 0.14.1 - * Linux、Macos or like unix - * Windows+bash +## 1. Requirements -Thrift (0.14.1 or higher) must be installed to compile Thrift files into Rust code. The following is the official installation tutorial, and in the end, you should receive a Thrift executable file. +- Rust 1.75+ +- Apache IoTDB 2.x — see [COMPATIBILITY.md](https://github.com/apache/iotdb-client-rust/blob/main/COMPATIBILITY.md) for the full server version matrix -``` -http://thrift.apache.org/docs/install/ -``` +## 2. Installation -## 2. Compile the Thrift library and generate the Rust native interface - -1. Find the `pom.xml` file in the root directory of the IoTDB source code folder. -2. Open the `pom.xml` file and find the following content: - ```xml - <execution> - <id>generate-thrift-sources-python</id> - <phase>generate-sources</phase> - <goals> - <goal>compile</goal> - </goals> - <configuration> - <generator>py</generator> - <outputDirectory>${project.build.directory}/generated-sources-python/</outputDirectory> - </configuration> - </execution> - ``` -3. Duplicate this block and change the `id`, `generator` and `outputDirectory` to this: - ```xml - <execution> - <id>generate-thrift-sources-rust</id> - <phase>generate-sources</phase> - <goals> - <goal>compile</goal> - </goals> - <configuration> - <generator>rs</generator> - <outputDirectory>${project.build.directory}/generated-sources-rust/</outputDirectory> - </configuration> - </execution> - ``` -4. In the root directory of the IoTDB source code folder,run `mvn clean generate-sources`. - -This command will automatically delete the files in `iotdb/iotdb-protocol/thrift/target` and `iotdb/iotdb-protocol/thrift-commons/target`, and repopulate the folder with the newly generated files. -The newly generated Rust sources will be located in `iotdb/iotdb-protocol/thrift/target/generated-sources-rust` in the various modules of the `iotdb-protocol` module. - -## 3. Using the Rust native interface - -Copy `iotdb/iotdb-protocol/thrift/target/generated-sources-rust/` and `iotdb/iotdb-protocol/thrift-commons/target/generated-sources-rust/` into your project。 - -## 4. RPC interface +Once published to crates.io: +```toml +[dependencies] +iotdb-client-rust = "0.1" ``` -// open a session -TSOpenSessionResp openSession(1:TSOpenSessionReq req); - -// close a session -TSStatus closeSession(1:TSCloseSessionReq req); - -// run an SQL statement in batch -TSExecuteStatementResp executeStatement(1:TSExecuteStatementReq req); - -// execute SQL statement in batch -TSStatus executeBatchStatement(1:TSExecuteBatchStatementReq req); - -// execute query SQL statement -TSExecuteStatementResp executeQueryStatement(1:TSExecuteStatementReq req); - -// execute insert, delete and update SQL statement -TSExecuteStatementResp executeUpdateStatement(1:TSExecuteStatementReq req); - -// fetch next query result -TSFetchResultsResp fetchResults(1:TSFetchResultsReq req) - -// fetch meta data -TSFetchMetadataResp fetchMetadata(1:TSFetchMetadataReq req) - -// cancel a query -TSStatus cancelOperation(1:TSCancelOperationReq req); - -// close a query dataset -TSStatus closeOperation(1:TSCloseOperationReq req); - -// get time zone -TSGetTimeZoneResp getTimeZone(1:i64 sessionId); - -// set time zone -TSStatus setTimeZone(1:TSSetTimeZoneReq req); - -// get server's properties -ServerProperties getProperties(); - -// CREATE DATABASE -TSStatus setStorageGroup(1:i64 sessionId, 2:string storageGroup); -// create timeseries -TSStatus createTimeseries(1:TSCreateTimeseriesReq req); +Until then, use a git dependency: -// create multi timeseries -TSStatus createMultiTimeseries(1:TSCreateMultiTimeseriesReq req); - -// delete timeseries -TSStatus deleteTimeseries(1:i64 sessionId, 2:list<string> path) - -// delete sttorage groups -TSStatus deleteStorageGroups(1:i64 sessionId, 2:list<string> storageGroup); - -// insert record -TSStatus insertRecord(1:TSInsertRecordReq req); - -// insert record in string format -TSStatus insertStringRecord(1:TSInsertStringRecordReq req); - -// insert tablet -TSStatus insertTablet(1:TSInsertTabletReq req); - -// insert tablets in batch -TSStatus insertTablets(1:TSInsertTabletsReq req); - -// insert records in batch -TSStatus insertRecords(1:TSInsertRecordsReq req); - -// insert records of one device -TSStatus insertRecordsOfOneDevice(1:TSInsertRecordsOfOneDeviceReq req); +```toml +[dependencies] +iotdb-client = { git = "https://github.com/apache/iotdb-client-rust" } +``` -// insert records in batch as string format -TSStatus insertStringRecords(1:TSInsertStringRecordsReq req); +The import name is `iotdb_client` in both cases. + +## 3. Quick start + +```rust +use iotdb_client::{Result, Session, SessionConfig, TSDataType, Tablet, Value}; + +fn main() -> Result<()> { + let config = SessionConfig::default().with_node_urls(&["127.0.0.1:6667"])?; + let mut session = Session::new(config); + session.open()?; + + session.execute_non_query("CREATE DATABASE root.demo")?; + session.execute_non_query( + "CREATE TIMESERIES root.demo.d1.temperature WITH DATATYPE=DOUBLE, ENCODING=PLAIN", + )?; + + // Batch write via a column-major tablet (nulls allowed). + let mut tablet = Tablet::new( + "root.demo.d1", + vec!["temperature".into()], + vec![TSDataType::Double], + )?; + tablet.add_row(1_720_000_000_000, vec![Some(Value::Double(21.5))])?; + tablet.add_row(1_720_000_001_000, vec![None])?; // null cell + session.insert_tablet(&tablet)?; + + // Or write a single row via insertRecord (aligned variants and + // multi-row insert_records / insert_records_of_one_device also exist). + session.insert_record( + "root.demo.d1", + 1_720_000_002_000, + vec!["temperature".into()], + &[Value::Double(22.0)], + false, // is_aligned + )?; + + // Query with row iteration; the dataset borrows the session until dropped. + { + let mut dataset = session.execute_query("SELECT temperature FROM root.demo.d1")?; + while let Some(row) = dataset.next_row()? { + println!("ts={:?} values={:?}", row.timestamp, row.values); + } + } + + session.execute_non_query("DELETE DATABASE root.demo")?; + session.close() +} +``` -// test the latency of innsert tablet,caution:no data will be inserted, only for test latency -TSStatus testInsertTablet(1:TSInsertTabletReq req); +## 4. Session pool + +`SessionPool` is a thread-safe pool for concurrent workloads. `acquire()` returns an RAII guard that releases the session back to the pool on drop: + +```rust +use std::sync::Arc; +use iotdb_client::{Result, SessionPool, SessionPoolConfig}; + +fn main() -> Result<()> { + let config = SessionPoolConfig { + max_size: 4, + ..SessionPoolConfig::default() + } + .with_node_urls(&["127.0.0.1:6667"])?; + let pool = Arc::new(SessionPool::new(config)?); + + let handles: Vec<_> = (0..4) + .map(|_| { + let pool = Arc::clone(&pool); + std::thread::spawn(move || -> Result<()> { + let mut session = pool.acquire()?; + session.execute_non_query("SHOW DATABASES")?; + Ok(()) + }) + }) + .collect(); + for handle in handles { + handle.join().expect("thread panicked")?; + } + + pool.close(); + Ok(()) +} +``` -// test the latency of innsert tablets,caution:no data will be inserted, only for test latency -TSStatus testInsertTablets(1:TSInsertTabletsReq req); +## 5. TLS & RPC compression -// test the latency of innsert record,caution:no data will be inserted, only for test latency -TSStatus testInsertRecord(1:TSInsertRecordReq req); +**RPC compression** (the Thrift compact protocol) must match the server setting `dn_rpc_thrift_compression_enable` (default `false`): -// test the latency of innsert record in string format,caution:no data will be inserted, only for test latency -TSStatus testInsertStringRecord(1:TSInsertStringRecordReq req); +```rust +let config = SessionConfig { enable_rpc_compression: true, ..Default::default() }; +``` -// test the latency of innsert records,caution:no data will be inserted, only for test latency -TSStatus testInsertRecords(1:TSInsertRecordsReq req); +**TLS** is behind the `tls` cargo feature: -// test the latency of innsert records of one device,caution:no data will be inserted, only for test latency -TSStatus testInsertRecordsOfOneDevice(1:TSInsertRecordsOfOneDeviceReq req); +```toml +iotdb-client-rust = { version = "0.1", features = ["tls"] } +``` -// test the latency of innsert records in string formate,caution:no data will be inserted, only for test latency -TSStatus testInsertStringRecords(1:TSInsertStringRecordsReq req); +```rust +let config = SessionConfig { + use_ssl: true, + ca_cert_path: Some("ca.pem".into()), // trust a private CA / self-signed cert + accept_invalid_certs: false, // true skips verification (tests only!) + domain_override: None, // SNI/validation hostname when connecting by IP + ..Default::default() +}; +``` -// delete data -TSStatus deleteData(1:TSDeleteDataReq req); +## 6. Examples -// execute raw data query -TSExecuteStatementResp executeRawDataQuery(1:TSRawDataQueryReq req); +Full runnable examples live in the repository's [`examples/`](https://github.com/apache/iotdb-client-rust/tree/main/examples) directory: -// request a statement id from server -i64 requestStatementId(1:i64 sessionId); +```sh +cargo run --example tree_session +cargo run --example table_session +cargo run --example session_pool ``` diff --git a/src/zh/UserGuide/Master/Table/API/Programming-Rust-Native-API_apache.md b/src/zh/UserGuide/Master/Table/API/Programming-Rust-Native-API_apache.md new file mode 100644 index 00000000..651fcc47 --- /dev/null +++ b/src/zh/UserGuide/Master/Table/API/Programming-Rust-Native-API_apache.md @@ -0,0 +1,133 @@ +<!-- + + 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. + +--> + +# Rust 原生接口 + +Apache IoTDB 提供官方 Rust 客户端 SDK:[apache/iotdb-client-rust](https://github.com/apache/iotdb-client-rust),基于 Thrift RPC 协议(默认端口 6667)。本文档介绍**表模型**(`TableSession` / `TableSessionPool`,关系型 SQL 方言);树模型另有单独文档。 + +## 1. 环境要求 + +- Rust 1.75+ +- Apache IoTDB 2.x — 完整的服务端版本兼容矩阵见 [COMPATIBILITY.md](https://github.com/apache/iotdb-client-rust/blob/main/COMPATIBILITY.md) + +## 2. 安装 + +发布到 crates.io 后: + +```toml +[dependencies] +iotdb-client-rust = "0.1" +``` + +在此之前,可使用 git 依赖: + +```toml +[dependencies] +iotdb-client = { git = "https://github.com/apache/iotdb-client-rust" } +``` + +两种方式的导入名均为 `iotdb_client`。 + +## 3. 快速上手 + +```rust +use iotdb_client::{ColumnCategory, Result, TSDataType, TableSession, Tablet, Value}; + +fn main() -> Result<()> { + let mut session = TableSession::builder() + .node_urls(&["127.0.0.1:6667"])? + .username("root") + .password("root") + .build()?; + + session.execute_non_query("CREATE DATABASE IF NOT EXISTS demo")?; + session.execute_non_query("USE demo")?; + session.execute_non_query( + "CREATE TABLE IF NOT EXISTS sensors (device_id STRING TAG, temperature DOUBLE FIELD)", + )?; + + // 列式 tablet 写入。columnCategories 不包含 TIME —— 时间列是隐式的。 + let mut tablet = Tablet::new_table( + "sensors", + vec!["device_id".into(), "temperature".into()], + vec![TSDataType::String, TSDataType::Double], + vec![ColumnCategory::Tag, ColumnCategory::Field], + )?; + tablet.add_row( + 1_720_000_000_000, + vec![ + Some(Value::String("dev-1".into())), + Some(Value::Double(21.5)), + ], + )?; + session.insert(&tablet)?; + + // 逐行迭代查询结果;dataset 在 drop 前借用 session。 + { + let mut dataset = + session.execute_query("SELECT time, device_id, temperature FROM sensors")?; + while let Some(row) = dataset.next_row()? { + println!("{:?}", row.values); + } + } + + session.execute_non_query("DROP DATABASE demo")?; + session.close() +} +``` + +## 4. 会话池 + +`TableSessionPool` 是面向并发场景的线程安全会话池;`acquire()` 返回 RAII guard,drop 时自动将会话归还池中。可参考可运行示例 [`session_pool`](https://github.com/apache/iotdb-client-rust/blob/main/examples/session_pool.rs)。 + +## 5. TLS 与 RPC 压缩 + +**RPC 压缩**(即 Thrift compact 协议)必须与服务端配置 `dn_rpc_thrift_compression_enable`(默认 `false`)保持一致: + +```rust +let mut session = TableSession::builder() + .node_urls(&["127.0.0.1:6667"])? + .enable_rpc_compression(true) + .build()?; +``` + +**TLS** 通过 `tls` cargo feature 启用: + +```toml +iotdb-client-rust = { version = "0.1", features = ["tls"] } +``` + +```rust +let mut session = TableSession::builder() + .node_urls(&["127.0.0.1:6667"])? + .use_ssl(true) + .ca_cert_path("ca.pem") + .build()?; +``` + +## 6. 示例 + +完整可运行示例见仓库 [`examples/`](https://github.com/apache/iotdb-client-rust/tree/main/examples) 目录: + +```sh +cargo run --example table_session +cargo run --example session_pool +``` diff --git a/src/zh/UserGuide/Master/Tree/API/Programming-Rust-Native-API.md b/src/zh/UserGuide/Master/Tree/API/Programming-Rust-Native-API.md index 32de0b42..36ee6c95 100644 --- a/src/zh/UserGuide/Master/Tree/API/Programming-Rust-Native-API.md +++ b/src/zh/UserGuide/Master/Tree/API/Programming-Rust-Native-API.md @@ -19,182 +19,149 @@ --> +# Rust 原生接口 -# Rust +Apache IoTDB 提供官方 Rust 客户端 SDK:[apache/iotdb-client-rust](https://github.com/apache/iotdb-client-rust)。它基于 Thrift RPC 协议(默认端口 6667),同时支持 IoTDB 的两种数据模型: -IoTDB 使用 Thrift 作为跨语言的 RPC 框架,因此可以通过 Thrift 提供的接口来实现对 IoTDB 的访问。本文档将介绍如何生成可访问 IoTDB 的原生 Rust 接口。 +- **树模型** — `Session` / `SessionPool`:设备/时间序列路径(`root.sg.d1.s1`),本文档主要介绍此模型 +- **表模型** — `TableSession` / `TableSessionPool`:关系型 SQL 方言 +## 1. 环境要求 -## 1. 依赖 +- Rust 1.75+ +- Apache IoTDB 2.x — 完整的服务端版本兼容矩阵见 [COMPATIBILITY.md](https://github.com/apache/iotdb-client-rust/blob/main/COMPATIBILITY.md) - * JDK >= 1.8 - * Rust >= 1.0.0 - * thrift 0.14.1 - * Linux、Macos 或其他类 unix 系统 - * Windows+bash (下载 IoTDB Go client 需要 git ,通过 WSL、cygwin、Git Bash 任意一种方式均可) +## 2. 安装 -必须安装 thrift(0.14.1 或更高版本)才能将 thrift 文件编译为 Rust 代码。下面是官方的安装教程,最终,您应该得到一个 thrift 可执行文件。 +发布到 crates.io 后: -``` -http://thrift.apache.org/docs/install/ +```toml +[dependencies] +iotdb-client-rust = "0.1" ``` +在此之前,可使用 git 依赖: -## 2. 编译 thrift 库,生成 Rust 原生接口 - -1. 在 IoTDB 源代码文件夹的根目录中找到 pom.xml 文件。 -2. 打开 pom.xml 文件,找到以下内容: - -```xml -<execution> - <id>generate-thrift-sources-java</id> - <phase>generate-sources</phase> - <goals> - <goal>compile</goal> - </goals> - <configuration> - <generator>java</generator> - <thriftExecutable>${thrift.exec.absolute.path}</thriftExecutable> - <thriftSourceRoot>${basedir}/src/main/thrift</thriftSourceRoot> - </configuration> -</execution> -``` -3. 参考该设置,在 pom.xml 文件中添加以下内容,用来生成 Rust 的原生接口: - -```xml -<execution> - <id>generate-thrift-sources-rust</id> - <phase>generate-sources</phase> - <goals> - <goal>compile</goal> - </goals> - <configuration> - <generator>rs</generator> - <thriftExecutable>${thrift.exec.absolute.path}</thriftExecutable> - <thriftSourceRoot>${basedir}/src/main/thrift</thriftSourceRoot> - <includes>**/common.thrift,**/client.thrift</includes> - <outputDirectory>${project.build.directory}/generated-sources-rust</outputDirectory> - </configuration> -</execution> +```toml +[dependencies] +iotdb-client = { git = "https://github.com/apache/iotdb-client-rust" } ``` -4. 在 IoTDB 源代码文件夹的根目录下,运行`mvn clean generate-sources`, - -这个指令将自动删除`iotdb/iotdb-protocol/thrift/target` 和 `iotdb/iotdb-protocol/thrift-commons/target`中的文件,并使用新生成的 thrift 文件重新填充该文件夹。 - -这个文件夹在 git 中会被忽略,并且**永远不应该被推到 git 中!** - -**注意**不要将`iotdb/iotdb-protocol/thrift/target` 和 `iotdb/iotdb-protocol/thrift-commons/target`上传到 git 仓库中 ! - -## 3. 使用 Rust 原生接口 - -将 `iotdb/iotdb-protocol/thrift/target/generated-sources-rust/` 和 `iotdb/iotdb-protocol/thrift-commons/target/generated-sources-rust/` 中的文件复制到您的项目中,即可使用。 - -## 4. 支持的 rpc 接口 - +两种方式的导入名均为 `iotdb_client`。 + +## 3. 快速上手 + +```rust +use iotdb_client::{Result, Session, SessionConfig, TSDataType, Tablet, Value}; + +fn main() -> Result<()> { + let config = SessionConfig::default().with_node_urls(&["127.0.0.1:6667"])?; + let mut session = Session::new(config); + session.open()?; + + session.execute_non_query("CREATE DATABASE root.demo")?; + session.execute_non_query( + "CREATE TIMESERIES root.demo.d1.temperature WITH DATATYPE=DOUBLE, ENCODING=PLAIN", + )?; + + // 通过列式 tablet 批量写入(允许 null)。 + let mut tablet = Tablet::new( + "root.demo.d1", + vec!["temperature".into()], + vec![TSDataType::Double], + )?; + tablet.add_row(1_720_000_000_000, vec![Some(Value::Double(21.5))])?; + tablet.add_row(1_720_000_001_000, vec![None])?; // null 单元格 + session.insert_tablet(&tablet)?; + + // 或通过 insertRecord 写入单行(还提供 aligned 变体以及 + // 多行的 insert_records / insert_records_of_one_device)。 + session.insert_record( + "root.demo.d1", + 1_720_000_002_000, + vec!["temperature".into()], + &[Value::Double(22.0)], + false, // is_aligned + )?; + + // 逐行迭代查询结果;dataset 在 drop 前借用 session。 + { + let mut dataset = session.execute_query("SELECT temperature FROM root.demo.d1")?; + while let Some(row) = dataset.next_row()? { + println!("ts={:?} values={:?}", row.timestamp, row.values); + } + } + + session.execute_non_query("DELETE DATABASE root.demo")?; + session.close() +} ``` -// 打开一个 session -TSOpenSessionResp openSession(1:TSOpenSessionReq req); - -// 关闭一个 session -TSStatus closeSession(1:TSCloseSessionReq req); - -// 执行一条 SQL 语句 -TSExecuteStatementResp executeStatement(1:TSExecuteStatementReq req); - -// 批量执行 SQL 语句 -TSStatus executeBatchStatement(1:TSExecuteBatchStatementReq req); - -// 执行查询 SQL 语句 -TSExecuteStatementResp executeQueryStatement(1:TSExecuteStatementReq req); - -// 执行插入、删除 SQL 语句 -TSExecuteStatementResp executeUpdateStatement(1:TSExecuteStatementReq req); - -// 向服务器取下一批查询结果 -TSFetchResultsResp fetchResults(1:TSFetchResultsReq req) - -// 获取元数据 -TSFetchMetadataResp fetchMetadata(1:TSFetchMetadataReq req) - -// 取消某次查询操作 -TSStatus cancelOperation(1:TSCancelOperationReq req); - -// 关闭查询操作数据集,释放资源 -TSStatus closeOperation(1:TSCloseOperationReq req); - -// 获取时区信息 -TSGetTimeZoneResp getTimeZone(1:i64 sessionId); -// 设置时区 -TSStatus setTimeZone(1:TSSetTimeZoneReq req); - -// 获取服务端配置 -ServerProperties getProperties(); - -// 设置 database -TSStatus setStorageGroup(1:i64 sessionId, 2:string storageGroup); - -// 创建时间序列 -TSStatus createTimeseries(1:TSCreateTimeseriesReq req); - -// 创建多条时间序列 -TSStatus createMultiTimeseries(1:TSCreateMultiTimeseriesReq req); - -// 删除时间序列 -TSStatus deleteTimeseries(1:i64 sessionId, 2:list<string> path) - -// 删除 database -TSStatus deleteStorageGroups(1:i64 sessionId, 2:list<string> storageGroup); - -// 按行插入数据 -TSStatus insertRecord(1:TSInsertRecordReq req); - -// 按 String 格式插入一条数据 -TSStatus insertStringRecord(1:TSInsertStringRecordReq req); - -// 按列插入数据 -TSStatus insertTablet(1:TSInsertTabletReq req); - -// 按列批量插入数据 -TSStatus insertTablets(1:TSInsertTabletsReq req); - -// 按行批量插入数据 -TSStatus insertRecords(1:TSInsertRecordsReq req); - -// 按行批量插入同属于某个设备的数据 -TSStatus insertRecordsOfOneDevice(1:TSInsertRecordsOfOneDeviceReq req); - -// 按 String 格式批量按行插入数据 -TSStatus insertStringRecords(1:TSInsertStringRecordsReq req); - -// 测试按列插入数据的延迟,注意:该接口不真实插入数据,只用来测试网络延迟 -TSStatus testInsertTablet(1:TSInsertTabletReq req); +## 4. 会话池 + +`SessionPool` 是线程安全的会话池,适用于并发场景。`acquire()` 返回 RAII guard,drop 时自动将会话归还池中: + +```rust +use std::sync::Arc; +use iotdb_client::{Result, SessionPool, SessionPoolConfig}; + +fn main() -> Result<()> { + let config = SessionPoolConfig { + max_size: 4, + ..SessionPoolConfig::default() + } + .with_node_urls(&["127.0.0.1:6667"])?; + let pool = Arc::new(SessionPool::new(config)?); + + let handles: Vec<_> = (0..4) + .map(|_| { + let pool = Arc::clone(&pool); + std::thread::spawn(move || -> Result<()> { + let mut session = pool.acquire()?; + session.execute_non_query("SHOW DATABASES")?; + Ok(()) + }) + }) + .collect(); + for handle in handles { + handle.join().expect("thread panicked")?; + } + + pool.close(); + Ok(()) +} +``` -// 测试批量按列插入数据的延迟,注意:该接口不真实插入数据,只用来测试网络延迟 -TSStatus testInsertTablets(1:TSInsertTabletsReq req); +## 5. TLS 与 RPC 压缩 -// 测试按行插入数据的延迟,注意:该接口不真实插入数据,只用来测试网络延迟 -TSStatus testInsertRecord(1:TSInsertRecordReq req); +**RPC 压缩**(即 Thrift compact 协议)必须与服务端配置 `dn_rpc_thrift_compression_enable`(默认 `false`)保持一致: -// 测试按 String 格式按行插入数据的延迟,注意:该接口不真实插入数据,只用来测试网络延迟 -TSStatus testInsertStringRecord(1:TSInsertStringRecordReq req); +```rust +let config = SessionConfig { enable_rpc_compression: true, ..Default::default() }; +``` -// 测试按行插入数据的延迟,注意:该接口不真实插入数据,只用来测试网络延迟 -TSStatus testInsertRecords(1:TSInsertRecordsReq req); +**TLS** 通过 `tls` cargo feature 启用: -// 测试按行批量插入同属于某个设备的数据的延迟,注意:该接口不真实插入数据,只用来测试网络延迟 -TSStatus testInsertRecordsOfOneDevice(1:TSInsertRecordsOfOneDeviceReq req); +```toml +iotdb-client-rust = { version = "0.1", features = ["tls"] } +``` -// 测试按 String 格式批量按行插入数据的延迟,注意:该接口不真实插入数据,只用来测试网络延迟 -TSStatus testInsertStringRecords(1:TSInsertStringRecordsReq req); +```rust +let config = SessionConfig { + use_ssl: true, + ca_cert_path: Some("ca.pem".into()), // 信任私有 CA / 自签名证书 + accept_invalid_certs: false, // true 跳过证书校验(仅限测试!) + domain_override: None, // 按 IP 连接时指定 SNI/校验主机名 + ..Default::default() +}; +``` -// 删除数据 -TSStatus deleteData(1:TSDeleteDataReq req); +## 6. 示例 -// 执行原始数据查询 -TSExecuteStatementResp executeRawDataQuery(1:TSRawDataQueryReq req); +完整可运行示例见仓库 [`examples/`](https://github.com/apache/iotdb-client-rust/tree/main/examples) 目录: -// 向服务器申请一个查询语句 ID -i64 requestStatementId(1:i64 sessionId); +```sh +cargo run --example tree_session +cargo run --example table_session +cargo run --example session_pool ``` diff --git a/src/zh/UserGuide/latest-Table/API/Programming-Rust-Native-API_apache.md b/src/zh/UserGuide/latest-Table/API/Programming-Rust-Native-API_apache.md new file mode 100644 index 00000000..651fcc47 --- /dev/null +++ b/src/zh/UserGuide/latest-Table/API/Programming-Rust-Native-API_apache.md @@ -0,0 +1,133 @@ +<!-- + + 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. + +--> + +# Rust 原生接口 + +Apache IoTDB 提供官方 Rust 客户端 SDK:[apache/iotdb-client-rust](https://github.com/apache/iotdb-client-rust),基于 Thrift RPC 协议(默认端口 6667)。本文档介绍**表模型**(`TableSession` / `TableSessionPool`,关系型 SQL 方言);树模型另有单独文档。 + +## 1. 环境要求 + +- Rust 1.75+ +- Apache IoTDB 2.x — 完整的服务端版本兼容矩阵见 [COMPATIBILITY.md](https://github.com/apache/iotdb-client-rust/blob/main/COMPATIBILITY.md) + +## 2. 安装 + +发布到 crates.io 后: + +```toml +[dependencies] +iotdb-client-rust = "0.1" +``` + +在此之前,可使用 git 依赖: + +```toml +[dependencies] +iotdb-client = { git = "https://github.com/apache/iotdb-client-rust" } +``` + +两种方式的导入名均为 `iotdb_client`。 + +## 3. 快速上手 + +```rust +use iotdb_client::{ColumnCategory, Result, TSDataType, TableSession, Tablet, Value}; + +fn main() -> Result<()> { + let mut session = TableSession::builder() + .node_urls(&["127.0.0.1:6667"])? + .username("root") + .password("root") + .build()?; + + session.execute_non_query("CREATE DATABASE IF NOT EXISTS demo")?; + session.execute_non_query("USE demo")?; + session.execute_non_query( + "CREATE TABLE IF NOT EXISTS sensors (device_id STRING TAG, temperature DOUBLE FIELD)", + )?; + + // 列式 tablet 写入。columnCategories 不包含 TIME —— 时间列是隐式的。 + let mut tablet = Tablet::new_table( + "sensors", + vec!["device_id".into(), "temperature".into()], + vec![TSDataType::String, TSDataType::Double], + vec![ColumnCategory::Tag, ColumnCategory::Field], + )?; + tablet.add_row( + 1_720_000_000_000, + vec![ + Some(Value::String("dev-1".into())), + Some(Value::Double(21.5)), + ], + )?; + session.insert(&tablet)?; + + // 逐行迭代查询结果;dataset 在 drop 前借用 session。 + { + let mut dataset = + session.execute_query("SELECT time, device_id, temperature FROM sensors")?; + while let Some(row) = dataset.next_row()? { + println!("{:?}", row.values); + } + } + + session.execute_non_query("DROP DATABASE demo")?; + session.close() +} +``` + +## 4. 会话池 + +`TableSessionPool` 是面向并发场景的线程安全会话池;`acquire()` 返回 RAII guard,drop 时自动将会话归还池中。可参考可运行示例 [`session_pool`](https://github.com/apache/iotdb-client-rust/blob/main/examples/session_pool.rs)。 + +## 5. TLS 与 RPC 压缩 + +**RPC 压缩**(即 Thrift compact 协议)必须与服务端配置 `dn_rpc_thrift_compression_enable`(默认 `false`)保持一致: + +```rust +let mut session = TableSession::builder() + .node_urls(&["127.0.0.1:6667"])? + .enable_rpc_compression(true) + .build()?; +``` + +**TLS** 通过 `tls` cargo feature 启用: + +```toml +iotdb-client-rust = { version = "0.1", features = ["tls"] } +``` + +```rust +let mut session = TableSession::builder() + .node_urls(&["127.0.0.1:6667"])? + .use_ssl(true) + .ca_cert_path("ca.pem") + .build()?; +``` + +## 6. 示例 + +完整可运行示例见仓库 [`examples/`](https://github.com/apache/iotdb-client-rust/tree/main/examples) 目录: + +```sh +cargo run --example table_session +cargo run --example session_pool +``` diff --git a/src/zh/UserGuide/latest/API/Programming-Rust-Native-API.md b/src/zh/UserGuide/latest/API/Programming-Rust-Native-API.md index 32de0b42..36ee6c95 100644 --- a/src/zh/UserGuide/latest/API/Programming-Rust-Native-API.md +++ b/src/zh/UserGuide/latest/API/Programming-Rust-Native-API.md @@ -19,182 +19,149 @@ --> +# Rust 原生接口 -# Rust +Apache IoTDB 提供官方 Rust 客户端 SDK:[apache/iotdb-client-rust](https://github.com/apache/iotdb-client-rust)。它基于 Thrift RPC 协议(默认端口 6667),同时支持 IoTDB 的两种数据模型: -IoTDB 使用 Thrift 作为跨语言的 RPC 框架,因此可以通过 Thrift 提供的接口来实现对 IoTDB 的访问。本文档将介绍如何生成可访问 IoTDB 的原生 Rust 接口。 +- **树模型** — `Session` / `SessionPool`:设备/时间序列路径(`root.sg.d1.s1`),本文档主要介绍此模型 +- **表模型** — `TableSession` / `TableSessionPool`:关系型 SQL 方言 +## 1. 环境要求 -## 1. 依赖 +- Rust 1.75+ +- Apache IoTDB 2.x — 完整的服务端版本兼容矩阵见 [COMPATIBILITY.md](https://github.com/apache/iotdb-client-rust/blob/main/COMPATIBILITY.md) - * JDK >= 1.8 - * Rust >= 1.0.0 - * thrift 0.14.1 - * Linux、Macos 或其他类 unix 系统 - * Windows+bash (下载 IoTDB Go client 需要 git ,通过 WSL、cygwin、Git Bash 任意一种方式均可) +## 2. 安装 -必须安装 thrift(0.14.1 或更高版本)才能将 thrift 文件编译为 Rust 代码。下面是官方的安装教程,最终,您应该得到一个 thrift 可执行文件。 +发布到 crates.io 后: -``` -http://thrift.apache.org/docs/install/ +```toml +[dependencies] +iotdb-client-rust = "0.1" ``` +在此之前,可使用 git 依赖: -## 2. 编译 thrift 库,生成 Rust 原生接口 - -1. 在 IoTDB 源代码文件夹的根目录中找到 pom.xml 文件。 -2. 打开 pom.xml 文件,找到以下内容: - -```xml -<execution> - <id>generate-thrift-sources-java</id> - <phase>generate-sources</phase> - <goals> - <goal>compile</goal> - </goals> - <configuration> - <generator>java</generator> - <thriftExecutable>${thrift.exec.absolute.path}</thriftExecutable> - <thriftSourceRoot>${basedir}/src/main/thrift</thriftSourceRoot> - </configuration> -</execution> -``` -3. 参考该设置,在 pom.xml 文件中添加以下内容,用来生成 Rust 的原生接口: - -```xml -<execution> - <id>generate-thrift-sources-rust</id> - <phase>generate-sources</phase> - <goals> - <goal>compile</goal> - </goals> - <configuration> - <generator>rs</generator> - <thriftExecutable>${thrift.exec.absolute.path}</thriftExecutable> - <thriftSourceRoot>${basedir}/src/main/thrift</thriftSourceRoot> - <includes>**/common.thrift,**/client.thrift</includes> - <outputDirectory>${project.build.directory}/generated-sources-rust</outputDirectory> - </configuration> -</execution> +```toml +[dependencies] +iotdb-client = { git = "https://github.com/apache/iotdb-client-rust" } ``` -4. 在 IoTDB 源代码文件夹的根目录下,运行`mvn clean generate-sources`, - -这个指令将自动删除`iotdb/iotdb-protocol/thrift/target` 和 `iotdb/iotdb-protocol/thrift-commons/target`中的文件,并使用新生成的 thrift 文件重新填充该文件夹。 - -这个文件夹在 git 中会被忽略,并且**永远不应该被推到 git 中!** - -**注意**不要将`iotdb/iotdb-protocol/thrift/target` 和 `iotdb/iotdb-protocol/thrift-commons/target`上传到 git 仓库中 ! - -## 3. 使用 Rust 原生接口 - -将 `iotdb/iotdb-protocol/thrift/target/generated-sources-rust/` 和 `iotdb/iotdb-protocol/thrift-commons/target/generated-sources-rust/` 中的文件复制到您的项目中,即可使用。 - -## 4. 支持的 rpc 接口 - +两种方式的导入名均为 `iotdb_client`。 + +## 3. 快速上手 + +```rust +use iotdb_client::{Result, Session, SessionConfig, TSDataType, Tablet, Value}; + +fn main() -> Result<()> { + let config = SessionConfig::default().with_node_urls(&["127.0.0.1:6667"])?; + let mut session = Session::new(config); + session.open()?; + + session.execute_non_query("CREATE DATABASE root.demo")?; + session.execute_non_query( + "CREATE TIMESERIES root.demo.d1.temperature WITH DATATYPE=DOUBLE, ENCODING=PLAIN", + )?; + + // 通过列式 tablet 批量写入(允许 null)。 + let mut tablet = Tablet::new( + "root.demo.d1", + vec!["temperature".into()], + vec![TSDataType::Double], + )?; + tablet.add_row(1_720_000_000_000, vec![Some(Value::Double(21.5))])?; + tablet.add_row(1_720_000_001_000, vec![None])?; // null 单元格 + session.insert_tablet(&tablet)?; + + // 或通过 insertRecord 写入单行(还提供 aligned 变体以及 + // 多行的 insert_records / insert_records_of_one_device)。 + session.insert_record( + "root.demo.d1", + 1_720_000_002_000, + vec!["temperature".into()], + &[Value::Double(22.0)], + false, // is_aligned + )?; + + // 逐行迭代查询结果;dataset 在 drop 前借用 session。 + { + let mut dataset = session.execute_query("SELECT temperature FROM root.demo.d1")?; + while let Some(row) = dataset.next_row()? { + println!("ts={:?} values={:?}", row.timestamp, row.values); + } + } + + session.execute_non_query("DELETE DATABASE root.demo")?; + session.close() +} ``` -// 打开一个 session -TSOpenSessionResp openSession(1:TSOpenSessionReq req); - -// 关闭一个 session -TSStatus closeSession(1:TSCloseSessionReq req); - -// 执行一条 SQL 语句 -TSExecuteStatementResp executeStatement(1:TSExecuteStatementReq req); - -// 批量执行 SQL 语句 -TSStatus executeBatchStatement(1:TSExecuteBatchStatementReq req); - -// 执行查询 SQL 语句 -TSExecuteStatementResp executeQueryStatement(1:TSExecuteStatementReq req); - -// 执行插入、删除 SQL 语句 -TSExecuteStatementResp executeUpdateStatement(1:TSExecuteStatementReq req); - -// 向服务器取下一批查询结果 -TSFetchResultsResp fetchResults(1:TSFetchResultsReq req) - -// 获取元数据 -TSFetchMetadataResp fetchMetadata(1:TSFetchMetadataReq req) - -// 取消某次查询操作 -TSStatus cancelOperation(1:TSCancelOperationReq req); - -// 关闭查询操作数据集,释放资源 -TSStatus closeOperation(1:TSCloseOperationReq req); - -// 获取时区信息 -TSGetTimeZoneResp getTimeZone(1:i64 sessionId); -// 设置时区 -TSStatus setTimeZone(1:TSSetTimeZoneReq req); - -// 获取服务端配置 -ServerProperties getProperties(); - -// 设置 database -TSStatus setStorageGroup(1:i64 sessionId, 2:string storageGroup); - -// 创建时间序列 -TSStatus createTimeseries(1:TSCreateTimeseriesReq req); - -// 创建多条时间序列 -TSStatus createMultiTimeseries(1:TSCreateMultiTimeseriesReq req); - -// 删除时间序列 -TSStatus deleteTimeseries(1:i64 sessionId, 2:list<string> path) - -// 删除 database -TSStatus deleteStorageGroups(1:i64 sessionId, 2:list<string> storageGroup); - -// 按行插入数据 -TSStatus insertRecord(1:TSInsertRecordReq req); - -// 按 String 格式插入一条数据 -TSStatus insertStringRecord(1:TSInsertStringRecordReq req); - -// 按列插入数据 -TSStatus insertTablet(1:TSInsertTabletReq req); - -// 按列批量插入数据 -TSStatus insertTablets(1:TSInsertTabletsReq req); - -// 按行批量插入数据 -TSStatus insertRecords(1:TSInsertRecordsReq req); - -// 按行批量插入同属于某个设备的数据 -TSStatus insertRecordsOfOneDevice(1:TSInsertRecordsOfOneDeviceReq req); - -// 按 String 格式批量按行插入数据 -TSStatus insertStringRecords(1:TSInsertStringRecordsReq req); - -// 测试按列插入数据的延迟,注意:该接口不真实插入数据,只用来测试网络延迟 -TSStatus testInsertTablet(1:TSInsertTabletReq req); +## 4. 会话池 + +`SessionPool` 是线程安全的会话池,适用于并发场景。`acquire()` 返回 RAII guard,drop 时自动将会话归还池中: + +```rust +use std::sync::Arc; +use iotdb_client::{Result, SessionPool, SessionPoolConfig}; + +fn main() -> Result<()> { + let config = SessionPoolConfig { + max_size: 4, + ..SessionPoolConfig::default() + } + .with_node_urls(&["127.0.0.1:6667"])?; + let pool = Arc::new(SessionPool::new(config)?); + + let handles: Vec<_> = (0..4) + .map(|_| { + let pool = Arc::clone(&pool); + std::thread::spawn(move || -> Result<()> { + let mut session = pool.acquire()?; + session.execute_non_query("SHOW DATABASES")?; + Ok(()) + }) + }) + .collect(); + for handle in handles { + handle.join().expect("thread panicked")?; + } + + pool.close(); + Ok(()) +} +``` -// 测试批量按列插入数据的延迟,注意:该接口不真实插入数据,只用来测试网络延迟 -TSStatus testInsertTablets(1:TSInsertTabletsReq req); +## 5. TLS 与 RPC 压缩 -// 测试按行插入数据的延迟,注意:该接口不真实插入数据,只用来测试网络延迟 -TSStatus testInsertRecord(1:TSInsertRecordReq req); +**RPC 压缩**(即 Thrift compact 协议)必须与服务端配置 `dn_rpc_thrift_compression_enable`(默认 `false`)保持一致: -// 测试按 String 格式按行插入数据的延迟,注意:该接口不真实插入数据,只用来测试网络延迟 -TSStatus testInsertStringRecord(1:TSInsertStringRecordReq req); +```rust +let config = SessionConfig { enable_rpc_compression: true, ..Default::default() }; +``` -// 测试按行插入数据的延迟,注意:该接口不真实插入数据,只用来测试网络延迟 -TSStatus testInsertRecords(1:TSInsertRecordsReq req); +**TLS** 通过 `tls` cargo feature 启用: -// 测试按行批量插入同属于某个设备的数据的延迟,注意:该接口不真实插入数据,只用来测试网络延迟 -TSStatus testInsertRecordsOfOneDevice(1:TSInsertRecordsOfOneDeviceReq req); +```toml +iotdb-client-rust = { version = "0.1", features = ["tls"] } +``` -// 测试按 String 格式批量按行插入数据的延迟,注意:该接口不真实插入数据,只用来测试网络延迟 -TSStatus testInsertStringRecords(1:TSInsertStringRecordsReq req); +```rust +let config = SessionConfig { + use_ssl: true, + ca_cert_path: Some("ca.pem".into()), // 信任私有 CA / 自签名证书 + accept_invalid_certs: false, // true 跳过证书校验(仅限测试!) + domain_override: None, // 按 IP 连接时指定 SNI/校验主机名 + ..Default::default() +}; +``` -// 删除数据 -TSStatus deleteData(1:TSDeleteDataReq req); +## 6. 示例 -// 执行原始数据查询 -TSExecuteStatementResp executeRawDataQuery(1:TSRawDataQueryReq req); +完整可运行示例见仓库 [`examples/`](https://github.com/apache/iotdb-client-rust/tree/main/examples) 目录: -// 向服务器申请一个查询语句 ID -i64 requestStatementId(1:i64 sessionId); +```sh +cargo run --example tree_session +cargo run --example table_session +cargo run --example session_pool ```
