---
sidebar_position: 5
sidebar_label: Rust
title: Rust Connector
---
import Preparition from "./_preparition.mdx"
[![Crates.io](https://img.shields.io/crates/v/libtaos)](https://crates.io/crates/libtaos) ![Crates.io](https://img.shields.io/crates/d/libtaos) [![docs.rs](https://img.shields.io/docsrs/libtaos)](https://docs.rs/libtaos)
`libtaos` 是 TDengine 的官方 Rust 语言连接器。Rust 语言开发人员可以通过它开发存取 TDengine 数据库的应用软件。`libtaos` 使用不同的 “特性(Rust Cargo 包管理关键字 features)” 提供对通过客户端驱动程序(taosc)原生连接和使用 REST 连接 TDengine 数据库。以下是可使用的特性列表:
| 启用特性 | 支持平台 | 说明 |
| -------- | --------------------- | ----------------------------------------------------------------- |
| default | Windows, Linux | 使用 TDengine 客户端驱动(taosc),支持 STMT 接口和行协议接口 |
| rest | Windows, Linux, macOS | 使用 HTTP REST API 接口(rest),适用于全平台 |
| (+)r2d2 | - | 使用 [r2d2] 提供的连接池接口,需要与 default 或 rest 特性配合使用 |
:::warning
Rust 连接器仍然在快速开发中,1.0 之前无法保证其向后兼容,请使用时注意版本及对应的文档。*
:::
## 版本支持
| 驱动 | 平台 | 最小支持版本 |
| :---: | :-----: | :--------------------------------: |
| taosc | Windows | 2.0.20.10 (行协议接口 >= 2.4.0.0) |
| taosc | Linux | 2.0.6.0 (行协议接口 >= 2.4.0.0) |
| rest | All | 2.0.0.0 (不支持 STMT 和行协议接口) |
建议使用 2.4 版本以上的 TDengine,以避免已知问题。
## 安装前准备
* 安装 Rust 开发工具链
之后可以按照如下说明在 [Rust](https://rust-lang.org) 项目中添加 [libtaos][libtaos] 依赖:
### 使用客户端驱动
在 `Cargo.toml` 文件中添加 [libtaos][libtaos]:
```toml
[dependencies]
# use default feature
libtaos = "*"
```
### 使用 REST 接口
在 `Cargo.toml` 文件中添加 [libtaos][libtaos],并启用 `rest` 特性。
```toml
[dependencies]
# use rest feature
libtaos = { version = "*", features = ["rest"]}
```
### 使用连接池
选择使用客户端驱动或 REST 接口,并在 `Cargo.toml` 中启用 `r2d2` 特性。
```toml
[dependencies]
# with taosc
libtaos = { version = "*", features = ["r2d2"] }
# or rest
libtaos = { version = "*", features = ["rest", "r2d2"] }
```
## 建立连接
[TaosCfgBuilder] 为使用者提供构造器形式的 API,以便于后续创建连接或使用连接池。
```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");
}
```
现在您可以使用该对象创建连接:
```rust
let conn = cfg.connect()?;
```
连接对象可以创建多个:
```rust
let conn = cfg.connect()?;
let conn2 = cfg.connect()?;
```
可以在应用中使用连接池:
```rust
let pool = r2d2::Pool::builder()
.max_size(10000) // 最大连接数
.build(cfg)?;
// ...
// Use pool to get connection
let conn = pool.get()?;
```
之后您可以对数据库进行相关操作:
```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(","));
}
}
```
## 使用示例
| 程序路径 | 程序说明 |
| -------------- | ----------------------------------------------------------------------------- |
| [demo.rs] | 基本API 使用示例 |
| [bailongma-rs] | 使用 TDengine 作为存储后端的 Prometheus 远程存储 API 适配器,使用 r2d2 连接池 |
## API 参考
### 连接构造器 API
[Builder Pattern](https://doc.rust-lang.org/1.0.0/style/ownership/builders.html) 构造器模式是 Rust 处理复杂数据类型或可选配置类型的解决方案。[libtaos] 实现中,使用连接构造器 [TaosCfgBuilder] 作为 TDengine Rust 连接器的入口。[TaosCfgBuilder] 提供对服务器、端口、数据库、用户名和密码等的可选配置。
使用 `default()` 方法可以构建一个默认参数的 [TaosCfg],用于后续连接数据库或建立连接池。
```rust
let cfg = TaosCfgBuilder::default().build()?;
```
使用构造器模式,用户可按需设置:
```rust
let cfg = TaosCfgBuilder::default()
.ip("127.0.0.1")
.user("root")
.pass("taosdata")
.db("log")
.port(6030u16)
.build()?;
```
使用 [TaosCfg] 对象创建 TDengine 连接:
```rust
let conn: Taos = cfg.connect();
```
### 连接池
在复杂应用中,建议启用连接池。[libtaos] 的连接池使用 [r2d2] 实现。
如下,可以生成一个默认参数的连接池。
```rust
let pool = r2d2::Pool::new(cfg)?;
```
同样可以使用连接池的构造器,对连接池参数进行设置:
```rust
use std::time::Duration;
let pool = r2d2::Pool::builder()
.max_size(5000) // 最大连接数
.max_lifetime(Some(Duration::from_minutes(100))) // 每个连接的最长存活时间
.min_idle(Some(1000)) // 最小空闲连接数
.connection_timeout(Duration::from_minutes(2)) // 连接超时时间
.build(cfg);
```
在应用代码中,使用 `pool.get()?` 来获取一个连接对象 [Taos]。
```rust
let taos = pool.get()?;
```
### 连接
[Taos] 结构体是 [libtaos] 中的连接管理者,主要提供了两个 API:
1. `exec`: 执行某个非查询类 SQL 语句,例如 `CREATE`,`ALTER`,`INSERT` 等。
```rust
taos.exec().await?;
```
2. `query`:执行查询语句,返回 [TaosQueryData] 对象。
```rust
let q = taos.query("select * from log.logs").await?;
```
[TaosQueryData] 对象存储了查询结果数据和返回的列的基本信息(列名,类型,长度):
列信息使用 [ColumnMeta] 存储:
```rust
let cols = &q.column_meta;
for col in cols {
println!("name: {}, type: {:?}, bytes: {}", col.name, col.type_, col.bytes);
}
```
逐行获取数据:
```rust
for (i, row) in q.rows.iter().enumerate() {
for (j, cell) in row.iter().enumerate() {
println!("cell({}, {}) data: {}", i, j, cell);
}
}
```
需要注意的是,需要使用 Rust 异步函数和异步运行时。
[Taos] 提供部分 SQL 的 Rust 方法化以减少 `format!` 代码块的频率:
- `.describe(table: &str)`: 执行 `DESCRIBE` 并返回一个 Rust 数据结构。
- `.create_database(database: &str)`: 执行 `CREATE DATABASE` 语句。
- `.use_database(database: &str)`: 执行 `USE` 语句。
除此之外,该结构也是 [参数绑定](#参数绑定接口) 和 [行协议接口](#行协议接口) 的入口,使用方法请参考具体的 API 说明。
### 参数绑定接口
与 C 接口类似,Rust 提供参数绑定接口。首先,通过 [Taos] 对象创建一个 SQL 语句的参数绑定对象 [Stmt]:
```rust
let mut stmt: Stmt = taos.stmt("insert into ? values(?,?)")?;
```
参数绑定对象提供了一组接口用于实现参数绑定:
#### `.set_tbname(tbname: impl ToCString)`
用于绑定表名。
#### `.set_tbname_tags(tbname: impl ToCString, tags: impl IntoParams)`
当 SQL 语句使用超级表时,用于绑定子表表名和标签值:
```rust
let mut stmt = taos.stmt("insert into ? using stb0 tags(?) values(?,?)")?;
// 可以创建任意类型的标签,以 JSON 类型为例。
let v = Field::Json(serde_json::from_str("{\"tag1\":\"一二三四五六七八九十\"}").unwrap());
stmt.set_tbname_tags("tb0", [&tag])?;
```
#### `.bind(params: impl IntoParams)`
用于绑定值类型。使用 [Field] 结构体构建需要的类型并绑定:
```rust
let ts = Field::Timestamp(Timestamp::now());
let value = Field::Float(0.0);
stmt.bind(vec![ts, value].iter())?;
```
#### `.execute()`
执行 SQL。[Stmt] 对象可以复用,在执行后可以重新绑定并执行。
```rust
stmt.execute()?;
// next bind cycle.
//stmt.set_tbname()?;
//stmt.bind()?;
//stmt.execute()?;
```
### 行协议接口
行协议接口支持多种模式和不同精度,需要引入 schemaless 模块中的常量以进行设置:
```rust
use libtaos::*;
use libtaos::schemaless::*;
```
- InfluxDB 行协议
```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 协议
```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 协议
```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)?;
```
其他相关结构体 API 使用说明请移步 Rust 文档托管网页:。
[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