--- toc_max_heading_level: 4 sidebar_position: 5 sidebar_label: Rust title: TDengine Rust Connector --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import Preparation from "./_preparation.mdx" import RustInsert from "../../07-develop/03-insert-data/_rust_sql.mdx" import RustInfluxLine from "../../07-develop/03-insert-data/_rust_line.mdx" import RustOpenTSDBTelnet from "../../07-develop/03-insert-data/_rust_opts_telnet.mdx" import RustOpenTSDBJson from "../../07-develop/03-insert-data/_rust_opts_json.mdx" import RustQuery from "../../07-develop/04-query-data/_rust.mdx" `libtaos` is the official Rust language connector for TDengine. Rust developers can develop applications to access the TDengine instance data. `libtaos` provides two ways to establish connections. One is the **Native Connection**, which connects to TDengine instances via the TDengine client driver (taosc). The other is **REST connection**, which connects to TDengine instances via taosAdapter's REST interface. The source code for `libtaos` is hosted on [GitHub](https://github.com/taosdata/libtaos-rs). ## Supported platforms The platforms supported by native connections are the same as those supported by the TDengine client driver. REST connections are supported on all platforms that can run Rust. ## Version support Please refer to [version support list](/reference/connector#version-support). The Rust Connector is still under rapid development and is not guaranteed to be backward compatible before 1.0. Recommend to use TDengine version 2.4 or higher to avoid known issues. ## Installation ### Pre-installation * Install the Rust development toolchain * If using the native connection, please install the TDengine client driver. Please refer to [install client driver](/reference/connector#install-client-driver) ### Adding libtaos dependencies Add the [libtaos][libtaos] dependency to the [Rust](https://rust-lang.org) project as follows, depending on the connection method selected. Add [libtaos][libtaos] to the ``Cargo.toml`'' file. ``toml [dependencies] # use default feature libtaos = "*" ``` Add [libtaos][libtaos] to the `Cargo.toml` file and enable the `rest` feature. ```toml [dependencies] # use rest feature libtaos = { version = "*", features = ["rest"]} ``` ### Using connection pools Please enable the `r2d2` feature in `Cargo.toml`. ```toml [dependencies] # with taosc libtaos = { version = "*", features = ["r2d2"] } # or rest libtaos = { version = "*", features = ["rest", "r2d2"] } ``` ## Create a connection The [TaosCfgBuilder] provides the user with an API in the form of a constructor for the subsequent creation of connections or use of connection pools. ```rust let cfg: TaosCfg = TaosCfgBuilder::default() .ip("127.0.0.1") .user("root") .pass("taosdata") .db("log") // do not set if not require a default database. .port(6030u16) .build() .expect("TaosCfg builder error"); } ``` 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? // change database context conn.exec("use demo").await? // create table conn.exec("create table if not exists tb1 (ts timestamp, v int)").await? // insert conn.exec("insert into tb1 values(now, 1)").await? // query let rows = conn.query("select * from tb1").await? for row in rows.rows { println!("{}", row.into_iter().join(",")); } } ``` ## Usage examples ### Write data #### SQL Write #### InfluxDB line protocol write #### OpenTSDB Telnet line protocol write #### OpenTSDB JSON line protocol write ### Query data ### More sample programs | Program Path | Program Description | | -------------- | ----------------------------------------------------------------------------- | | [demo.rs] | Basic API Usage Examples | | [bailongma-rs] | Using TDengine as the Prometheus remote storage API adapter for the storage backend, using the r2d2 connection pool | ## API Reference ### Connection constructor API The [Builder Pattern](https://doc.rust-lang.org/1.0.0/style/ownership/builders.html) constructor pattern is Rust's solution for handling complex data types or optional configuration types. The [libtaos] implementation uses the connection constructor [TaosCfgBuilder] as the entry point for the TDengine Rust connector. The [TaosCfgBuilder] provides optional configuration of servers, ports, databases, usernames, passwords, etc. Using the `default()` method, you can construct a [TaosCfg] with default parameters for subsequent connections to the database or establishing connection pools. ```rust let cfg = TaosCfgBuilder::default().build()? ; ``` Using the constructor pattern, the user can set on-demand. ```rust let cfg = TaosCfgBuilder::default() .ip("127.0.0.1") .user("root") .pass("taosdata") .db("log") .port(6030u16) .build()? ; ``` Create TDengine connection using [TaosCfg] object. ```rust let conn: Taos = cfg.connect(); ``` ### Connection pooling In complex applications, recommand to enable connection pool. 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 partial Rust methodization of 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. - `.use_database(database: &str)`: Executes the `USE` statement. In addition, this structure is also the entry point for [Parameter Binding](#Parameter Binding Interface) and [Line Protocol Interface](#Line Protocol Interface). Please refer to the specific API descriptions for usage. ### Bind Interface Similar to the C interface, Rust provides the bind interface's wraping. First, create a bind object [Stmt] for a SQL command from the [Taos] object. ```rust let mut stmt: Stmt = taos.stmt("insert into ? values(? ,?)") ? ; ``` The bind object provides a set of interfaces for implementing parameter binding. ##### `.set_tbname(tbname: impl ToCString)` To bind table names. ##### `.set_tbname_tags(tbname: impl ToCString, tags: impl IntoParams)` Bind sub-table table names and tag values when the SQL statement uses a super table. ```rust let mut stmt = taos.stmt("insert into ? using stb0 tags(?) values(? ,?)") ? ; // tags can be created with any supported type, here is an example using JSON let v = Field::Json(serde_json::from_str("{\"tag1\":\"one, two, three, four, five, six, seven, eight, nine, ten\"}").unwrap()); stmt.set_tbname_tags("tb0", [&tag])? ; ``` ##### `.bind(params: impl IntoParams)` Bind value types. Use the [Field] structure to construct the desired type and bind. ```rust let ts = Field::Timestamp(Timestamp::now()); let value = Field::Float(0.0); stmt.bind(vec![ts, value].iter())? ; ``` ##### `.execute()` Execute SQL.[Stmt] objects can be reused, re-binded, and executed after execution. ```rust stmt.execute()? ; // next bind cycle. // stmt.set_tbname()? ; //stmt.bind()? ; //stmt.execute()? ; ``` ### Line protocol interface The line protocol interface supports multiple modes and different precision and requires the introduction of constants in the schemaless module to set. ```rust use libtaos::*; use libtaos::schemaless::*; ``` - InfluxDB line protocol ```rust let lines = [ "st,t1=abc,t2=def,t3=anything c1=3i64,c3=L\"pass\",c2=false 1626006833639000000" "st,t1=abc,t2=def,t3=anything c1=3i64,c3=L\"abc\",c4=4f64 1626006833639000000" ]; taos.schemaless_insert(&lines, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANOSECONDS)? ; ``` - OpenTSDB Telnet Protocol ```rust let lines = ["sys.if.bytes.out 1479496100 1.3E3 host=web01 interface=eth0"]; taos.schemaless_insert(&lines, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_SECONDS)? ; ``` - OpenTSDB JSON protocol ```rust let lines = [r#" { "metric": "st", "timestamp": 1626006833, "value": 10, "tags": { "t1": true, "t2": false, "t3": 10, "t4": "123_abc_.! @#$%^&*:;,. /? |+-=()[]{}<>" } }"#]; taos.schemaless_insert(&lines, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_SECONDS)? ; ``` 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 [bailongma-rs]: https://github.com/taosdata/bailongma-rs [r2d2]: https://crates.io/crates/r2d2 [demo.rs]: https://github.com/taosdata/libtaos-rs/blob/main/examples/demo.rs [TaosCfgBuilder]: https://docs.rs/libtaos/latest/libtaos/struct.TaosCfgBuilder.html [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 [Stmt]: https://docs.rs/libtaos/latest/libtaos/stmt/struct.Stmt.html