--- 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 Preparition from "./_preparition.mdx" import RustInsert from "../../04-develop/03-insert-data/_rust_sql.mdx" import RustInfluxLine from "../../04-develop/03-insert-data/_rust_line.mdx" import RustOpenTSDBTelnet from "../../04-develop/03-insert-data/_rust_opts_telnet.mdx" import RustOpenTSDBJson from "../../04-develop/03-insert-data/_rust_opts_json.mdx" import RustQuery from "../../04-develop/04-query-data/_rust.mdx" `libtaos` is the official Rust language connector for TDengine, through which Rust developers can develop applications that access the TDengine database. `libtaos` provides two ways to establish connections. One is the **Native Connection**, which connects to TDengine runtime instances via the TDengine client driver (taosc). The other is **REST connection**, which connects to TDengine runtime instances via taosAdapter's REST interface. The REST connection supports any platform, but the native connection supports all platforms on which the TDengine client can run. 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 pooling. Connection pooling 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. ### Parameter Binding Interface Similar to the C interface, Rust provides a parameter binding interface. First, create a parameter binding object [Stmt] for a SQL statement from the [Taos] object. ```rust let mut stmt: Stmt = taos.stmt("insert into ? values(? ,?)") ? ; ``` The parameter binding 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