From 56247e26f80504314e89e7314d9f9935e2fa73de Mon Sep 17 00:00:00 2001 From: dingbo Date: Fri, 17 Jun 2022 15:16:01 +0800 Subject: [PATCH] docs: rust --- docs/en/05-develop/03-insert-data.md | 11 ++ docs/en/05-develop/04-query-data.md | 19 ++ docs/en/09-connector/rust.md | 171 ++++++++++++++++++ .../rust/cloud-example/examples/tutorial.rs | 37 ++++ 4 files changed, 238 insertions(+) create mode 100644 docs/en/09-connector/rust.md create mode 100644 docs/examples/rust/cloud-example/examples/tutorial.rs diff --git a/docs/en/05-develop/03-insert-data.md b/docs/en/05-develop/03-insert-data.md index 74179f88ee..6f3d71bdf8 100644 --- a/docs/en/05-develop/03-insert-data.md +++ b/docs/en/05-develop/03-insert-data.md @@ -50,7 +50,18 @@ In this example, we use `execute` method to execute SQL and get affected rows. T + +In this example, we use `exec` method to execute SQL. `exec` is designed for some non-query SQL statements, all returned data would be ignored. + +```rust +{{#include docs/examples/rust/cloud-example/examples/tutorial.rs:insert}} +``` + + +:::note +`Use` statement is not applicable for cloud service since REST API is stateless. +::: \ No newline at end of file diff --git a/docs/en/05-develop/04-query-data.md b/docs/en/05-develop/04-query-data.md index ec17896cb3..3fa44a21c3 100644 --- a/docs/en/05-develop/04-query-data.md +++ b/docs/en/05-develop/04-query-data.md @@ -150,6 +150,25 @@ Iterate over each rows: + +In this example, we use query method to execute SQL and get a result object. + +```rust +{{#include docs/examples/rust/cloud-example/examples/tutorial.rs:query:nrc}} +``` + +Get column meta from the result: + +```rust +{{#include docs/examples/rust/cloud-example/examples/tutorial.rs:meta:nrc}} +``` + +Get all rows and print each row: + +```rust +{{#include docs/examples/rust/cloud-example/examples/tutorial.rs:iter}} +``` + diff --git a/docs/en/09-connector/rust.md b/docs/en/09-connector/rust.md new file mode 100644 index 0000000000..8aead88139 --- /dev/null +++ b/docs/en/09-connector/rust.md @@ -0,0 +1,171 @@ +--- +toc_max_heading_level: 4 +sidebar_position: 5 +sidebar_label: Rust +title: TDengine Rust Connector +--- + + +`libtaos` is the official Rust language connector for TDengine. Rust developers can develop applications to access the TDengine instance data. + +The source code for `libtaos` is hosted on [GitHub](https://github.com/taosdata/libtaos-rs). + +## Installation + +### Pre-installation + +Install the Rust development toolchain. + +### Adding libtaos dependencies + +```toml +[dependencies] +# use rest feature +libtaos = { version = "*", features = ["rest"]} +``` + +### Using connection pools + +Please enable the `r2d2` feature in `Cargo.toml`. + +```toml +[dependencies] +libtaos = { version = "*", features = ["rest", "r2d2"] } +``` + +## Create a connection + +Create `TaosCfg` from TDengine cloud DSN. The DSN should be in form of `://[:port]?token=`. + +```rust +use libtaos::*; +let cfg = TaosCfg::from_dsn(DSN)?; +``` + +You can now use this object to create the connection. + +```rust +let conn = cfg.connect()? ; +``` + +The connection object can create more than one. + +```rust +let conn = cfg.connect()? ; +let conn2 = cfg.connect()? ; +``` + +You can use connection pools in applications. + +```rust +let pool = r2d2::Pool::builder() + .max_size(10000) // max connections + .build(cfg)? ; + +// ... +// Use pool to get connection +let conn = pool.get()? ; +``` + +After that, you can perform the following operations on the database. + +```rust +async fn demo() -> Result<(), Error> { + // get connection ... + + // create database + conn.exec("create database if not exists demo").await? + // create table + conn.exec("create table if not exists demo.tb1 (ts timestamp, v int)").await? + // insert + conn.exec("insert into demo.tb1 values(now, 1)").await? + // query + let rows = conn.query("select * from demo.tb1").await? + for row in rows.rows { + println!("{}", row.into_iter().join(",")); + } +} +``` + +## API Reference + +### Connection pooling + +In complex applications, we recommend enabling connection pools. Connection pool for [libtaos] is implemented using [r2d2]. + +As follows, a connection pool with default parameters can be generated. + +```rust +let pool = r2d2::Pool::new(cfg)? ; +``` + +You can set the same connection pool parameters using the connection pool's constructor. + +```rust + use std::time::Duration; + let pool = r2d2::Pool::builder() + .max_size(5000) // max connections + .max_lifetime(Some(Duration::from_minutes(100))) // lifetime of each connection + .min_idle(Some(1000)) // minimal idle connections + .connection_timeout(Duration::from_minutes(2)) + .build(cfg); +``` + +In the application code, use `pool.get()? ` to get a connection object [Taos]. + +```rust +let taos = pool.get()? ; +``` + +The [Taos] structure is the connection manager in [libtaos] and provides two main APIs. + +1. `exec`: Execute some non-query SQL statements, such as `CREATE`, `ALTER`, `INSERT`, etc. + + ```rust + taos.exec().await? + ``` + +2. `query`: Execute the query statement and return the [TaosQueryData] object. + + ```rust + let q = taos.query("select * from log.logs").await? + ``` + + The [TaosQueryData] object stores the query result data and basic information about the returned columns (column name, type, length). + + Column information is stored using [ColumnMeta]. + + ```rust + let cols = &q.column_meta; + for col in cols { + println!("name: {}, type: {:?} , bytes: {}", col.name, col.type_, col.bytes); + } + ``` + + It fetches data line by line. + + ```rust + for (i, row) in q.rows.iter().enumerate() { + for (j, cell) in row.iter().enumerate() { + println!("cell({}, {}) data: {}", i, j, cell); + } + } + ``` + +Note that Rust asynchronous functions and an asynchronous runtime are required. + +[Taos] provides a few Rust methods that encapsulate SQL to reduce the frequency of `format!` code blocks. + +- `.describe(table: &str)`: Executes `DESCRIBE` and returns a Rust data structure. +- `.create_database(database: &str)`: Executes the `CREATE DATABASE` statement. + + +Please move to the Rust documentation hosting page for other related structure API usage instructions: . + +[libtaos]: https://github.com/taosdata/libtaos-rs +[tdengine]: https://github.com/taosdata/TDengine +[r2d2]: https://crates.io/crates/r2d2 +[TaosCfg]: https://docs.rs/libtaos/latest/libtaos/struct.TaosCfg.html +[Taos]: https://docs.rs/libtaos/latest/libtaos/struct.Taos.html +[TaosQueryData]: https://docs.rs/libtaos/latest/libtaos/field/struct.TaosQueryData.html +[Field]: https://docs.rs/libtaos/latest/libtaos/field/enum.Field.html diff --git a/docs/examples/rust/cloud-example/examples/tutorial.rs b/docs/examples/rust/cloud-example/examples/tutorial.rs new file mode 100644 index 0000000000..401d8fa8d8 --- /dev/null +++ b/docs/examples/rust/cloud-example/examples/tutorial.rs @@ -0,0 +1,37 @@ +use anyhow::Result; +use libtaos::*; + +#[tokio::main] +async fn main() -> Result<()> { + let dsn = std::env::var("TDENGINE_CLOUD_DSN")?; + let cfg = TaosCfg::from_dsn(dsn)?; + let conn = cfg.connect()?; + //ANCHOR: insert +conn.exec("DROP DATABASE IF EXISTS power").await?; +conn.exec("CREATE DATABASE power").await?; +conn.exec("CREATE STABLE power.meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (location BINARY(64), groupId INT)").await?; +conn.exec("INSERT INTO power.d1001 USING power.meters TAGS(California.SanFrancisco, 2) VALUES ('2018-10-03 14:38:05.000', 10.30000, 219, 0.31000) ('2018-10-03 14:38:15.000', 12.60000, 218, 0.33000) ('2018-10-03 14:38:16.800', 12.30000, 221, 0.31000) +power.d1002 USING power.meters TAGS(California.SanFrancisco, 3) VALUES ('2018-10-03 14:38:16.650', 10.30000, 218, 0.25000) +").await?; + //ANCHOR_END: insert + // ANCHOR: query +let result = conn.query("SELECT ts, current FROM power.meters LIMIT 2").await?; + // ANCHOR_END: query + // ANCHOR: meta +let meta: Vec = result.column_meta; +for column in meta { + println!("name:{} bytes: {}", column.name, column.bytes) +} +// name:ts bytes: 8 +// name:current bytes: 4 + // ANCHOR_END: meta + // ANCHOR: iter +let rows: Vec> = result.rows; +for row in rows { + println!("{} {}", row[0].as_timestamp().unwrap(), row[1].as_float().unwrap()); +} +// 2018-10-03 14:38:05.000 10.3 +// 2018-10-03 14:38:15.000 12.6 + // ANCHOR_END: iter + Ok(()) +} -- GitLab