diff --git a/README-CN.md b/README-CN.md new file mode 100644 index 00000000..fb65924b --- /dev/null +++ b/README-CN.md @@ -0,0 +1,132 @@ + +# TDengine Rust Connector + + +| Docs.rs | Crates.io Version | Crates.io Downloads | CodeCov | +| ---------------------------------------------- | -------------------------------------------------- | -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ![docs.rs](https://img.shields.io/docsrs/taos) | ![Crates.io](https://img.shields.io/crates/v/taos) | ![Crates.io](https://img.shields.io/crates/d/taos) | [![codecov](https://codecov.io/gh/taosdata/taos-connector-rust/branch/main/graph/badge.svg?token=P11UKNLTVO)](https://codecov.io/gh/taosdata/taos-connector-rust) | + +简体中文 | [English](./README.md) + + +## 目录 + + +- [1. 简介](#1-简介) + - [1.1 连接方式](#11-连接方式) + - [1.2 Rust 版本兼容性](#12-rust-版本兼容性) + - [1.3 支持的平台](#13-支持的平台) +- [2. 获取驱动](#2-获取驱动) +- [3. 文档](#3-文档) +- [4. 前置条件](#4-前置条件) +- [5. 构建](#5-构建) +- [6. 测试](#6-测试) + - [6.1 运行测试](#61-运行测试) + - [6.2 添加用例](#62-添加用例) + - [6.3 性能测试](#63-性能测试) +- [7. 提交 Issue](#7-提交-issue) +- [8. 提交 PR](#8-提交-pr) +- [9. 引用](#9-引用) +- [10. 许可证](#10-许可证) + +## 1. 简介 + +`taos` 是 TDengine 的官方 Rust 语言连接器,Rust 开发人员可以通过它开发存取 TDengine 数据库的应用软件。它支持数据写入、数据查询、数据订阅、无模式写入以及参数绑定等功能。 + +### 1.1 连接方式 + +`taos` 提供了两种建立连接的方式: + +- 原生连接:通过客户端驱动程序 taosc 直接与服务端程序 taosd 建立连接。采用这种连接方式时,需确保客户端的驱动程序 taosc 与服务端的 taosd 版本保持一致。 +- WebSocket 连接:通过 taosAdapter 组件提供的 WebSocket API 建立与 taosd 的连接。此方式不依赖 TDengine 客户端驱动,支持跨平台使用,更为便捷灵活,且性能与原生连接相近。 + +建议使用 WebSocket 连接方式。详细说明请参考 [连接方式](https://docs.taosdata.com/develop/connect/#%E8%BF%9E%E6%8E%A5%E6%96%B9%E5%BC%8F)。 + +### 1.2 Rust 版本兼容性 + +支持 Rust 1.70 及以上版本。 + +### 1.3 支持的平台 + +- 原生连接支持的平台与 TDengine 客户端驱动支持的平台一致。 +- WebSocket 连接支持所有能运行 Rust 的平台。 + +## 2. 获取驱动 + +将以下内容添加到 `Cargo.toml`: + +```toml +[dependencies] +taos = "0.12.3" +``` + +## 3. 文档 + +- 开发示例请访问 [开发指南](https://docs.taosdata.com/develop/),其中包括数据写入、数据查询、数据订阅、无模式写入以及参数绑定等示例。 +- 更多信息请访问 [参考手册](https://docs.taosdata.com/reference/connector/rust/),其中包括版本历史、数据类型映射、示例程序汇总、API 参考以及常见问题等内容。 + +## 4. 前置条件 + +- 已安装 Rust 1.70 及以上版本。 +- 本地已部署 TDengine,具体步骤请参考 [部署服务端](https://docs.taosdata.com/get-started/package/),且已经启动 taosd 与 taosAdapter。 + +## 5. 构建 + +在项目目录下运行以下命令以构建项目: + +```sh +cargo build +``` + +## 6. 测试 + +### 6.1 运行测试 + +运行测试前,请在 `taos.cfg` 文件中添加以下配置: + +```text +supportVnodes 256 +``` + +完成配置后,在项目目录下执行以下命令运行测试: + +```sh +cargo test +``` + +### 6.2 添加用例 + +在相应的 `.rs` 文件的 `#[cfg(test)]` 模块内添加测试用例。对于同步代码,使用 `#[test]` 宏;对于异步代码,使用 `#[tokio::test]` 宏。 + +### 6.3 性能测试 + +性能测试正在开发中。 + +## 7. 提交 Issue + +我们欢迎提交 [GitHub Issue](https://github.com/taosdata/taos-connector-rust/issues/new?template=Blank+issue)。提交时请说明下面信息: + +- 问题描述,是否必现,最好能包含详细调用堆栈。 +- Rust 连接器版本。 +- 连接参数(不需要用户名密码)。 +- TDengine 服务端版本。 + +## 8. 提交 PR + +我们欢迎开发者一起开发本项目,提交 PR 时请参考下面步骤: + +1. Fork 本项目,请参考 ([how to fork a repo](https://docs.github.com/en/get-started/quickstart/fork-a-repo))。 +2. 从 main 分支创建一个新分支,请使用有意义的分支名称 (`git checkout -b my_branch`)。注意不要直接在 main 分支上修改。 +3. 修改代码,保证所有单元测试通过,并增加新的单元测试验证修改。 +4. 提交修改到远端分支 (`git push origin my_branch`)。 +5. 在 GitHub 上创建一个 Pull Request ([how to create a pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request))。 +6. 提交 PR 后,如果 CI 通过,可以在 [codecov](https://app.codecov.io/gh/taosdata/taos-connector-rust/pulls) 页面找到自己 PR,看单测覆盖率。 + +## 9. 引用 + +- [TDengine 官网](https://www.taosdata.com/) +- [TDengine GitHub](https://github.com/taosdata/TDengine) + +## 10. 许可证 + +[MIT License](./LICENSE) diff --git a/README.md b/README.md index 93717b39..8a211590 100644 --- a/README.md +++ b/README.md @@ -1,241 +1,132 @@ -# The Official Rust Connector for [TDengine] + +# TDengine Rust Connector + | Docs.rs | Crates.io Version | Crates.io Downloads | CodeCov | | ---------------------------------------------- | -------------------------------------------------- | -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ![docs.rs](https://img.shields.io/docsrs/taos) | ![Crates.io](https://img.shields.io/crates/v/taos) | ![Crates.io](https://img.shields.io/crates/d/taos) | [![codecov](https://codecov.io/gh/taosdata/taos-connector-rust/branch/main/graph/badge.svg?token=P11UKNLTVO)](https://codecov.io/gh/taosdata/taos-connector-rust) | -This is the official TDengine connector in Rust. +English | [简体中文](./README-CN.md) -## Dependencies + +## Table of Contents + -- [Rust](https://www.rust-lang.org/learn/get-started) of course. +- [1. Introduction](#1-introduction) + - [1.1 Connection Methods](#11-connection-methods) + - [1.2 Rust Version Compatibility](#12-rust-version-compatibility) + - [1.3 Supported Platforms](#13-supported-platforms) +- [2. Getting the Driver](#2-getting-the-driver) +- [3. Documentation](#3-documentation) +- [4. Prerequisites](#4-prerequisites) +- [5. Build](#5-build) +- [6. Testing](#6-testing) + - [6.1 Test Execution](#61-test-execution) + - [6.2 Test Case Addition](#62-test-case-addition) + - [6.3 Performance Testing](#63-performance-testing) +- [7. Submitting Issues](#7-submitting-issues) +- [8. Submitting PRs](#8-submitting-prs) +- [9. References](#9-references) +- [10. License](#10-license) -if you use the default features, it'll depend on: +## 1. Introduction -- [TDengine] Client library and headers. +`taos` is the official Rust language connector of TDengine, through which Rust developers can develop applications that access TDengine databases. It supports data writing, data query, data subscription, schemaless writing, parameter binding and other functions. -## Usage +### 1.1 Connection Methods -By default, enable both native and websocket client: +`taos` provides two ways to establish a connection: -```toml -[dependencies] -taos = "*" -``` +- Native connection: Establish a connection directly with the server program taosd through the client driver taosc. When using this connection method, you need to ensure that the client driver taosc and the server taosd version are consistent. +- WebSocket connection: Establish a connection with taosd through the WebSocket API provided by the taosAdapter component. This method does not rely on the TDengine client driver, supports cross-platform use, is more convenient and flexible, and has performance similar to native connection. + +It is recommended to use the WebSocket connection method. For detailed description, please refer to [Connection Methods](https://docs.tdengine.com/developer-guide/connecting-to-tdengine/#connection-methods). + +### 1.2 Rust Version Compatibility + +Supports Rust 1.70 and above. + +### 1.3 Supported Platforms -For websocket client only: +- The platforms supported by the native connection are consistent with those supported by the TDengine client driver. +- WebSocket connection supports all platforms that can run Rust. + +## 2. Getting the Driver + +Add the following to your `Cargo.toml`: ```toml [dependencies] -taos = { version = "*", default-features = false, features = ["ws"] } +taos = "0.12.3" ``` -For native only: +## 3. Documentation -```toml -[dependencies] -taos = { version = "*", default-features = false, features = ["native"] } +- For development examples, please visit the [Developer Guide](https://docs.tdengine.com/developer-guide/), which includes examples of data writing, data querying, data subscription, schemaless writing, and parameter binding. +- For more information, please visit the [Reference Manual](https://docs.tdengine.com/tdengine-reference/client-libraries/rust/), which includes version history, data type mapping, sample program summary, API reference, and FAQ. + +## 4. Prerequisites + +- Rust 1.70 or above has been installed. +- TDengine has been deployed locally. For specific steps, please refer to [Deploy TDengine](https://docs.tdengine.com/get-started/deploy-from-package/), and taosd and taosAdapter have been started. + +## 5. Build + +Run the following command in the project directory to build the project: + +```sh +cargo build ``` -### Query - -```rust -use chrono::{DateTime, Local}; -use taos::*; - -#[tokio::main] -async fn main() -> anyhow::Result<()> { - let dsn = "taos://localhost:6030"; - let builder = TaosBuilder::from_dsn(dsn)?; - - let taos = builder.build()?; - - let db = "query"; - - // prepare database - taos.exec_many([ - format!("DROP DATABASE IF EXISTS `{db}`"), - format!("CREATE DATABASE `{db}`"), - format!("USE `{db}`"), - ]) - .await?; - - let inserted = taos.exec_many([ - // create super table - "CREATE TABLE `meters` (`ts` TIMESTAMP, `current` FLOAT, `voltage` INT, `phase` FLOAT) \ - TAGS (`groupid` INT, `location` BINARY(16))", - // create child table - "CREATE TABLE `d0` USING `meters` TAGS(0, 'Los Angles')", - // insert into child table - "INSERT INTO `d0` values(now - 10s, 10, 116, 0.32)", - // insert with NULL values - "INSERT INTO `d0` values(now - 8s, NULL, NULL, NULL)", - // insert and automatically create table with tags if not exists - "INSERT INTO `d1` USING `meters` TAGS(1, 'San Francisco') values(now - 9s, 10.1, 119, 0.33)", - // insert many records in a single sql - "INSERT INTO `d1` values (now-8s, 10, 120, 0.33) (now - 6s, 10, 119, 0.34) (now - 4s, 11.2, 118, 0.322)", - ]).await?; - - assert_eq!(inserted, 6); - let mut result = taos.query("select * from `meters`").await?; - - for field in result.fields() { - println!("got field: {}", field.name()); - } - - // Query option 1, use rows stream. - let mut rows = result.rows(); - while let Some(row) = rows.try_next().await? { - for (name, value) in row { - println!("got value of {}: {}", name, value); - } - } - - // Query options 2, use deserialization with serde. - #[derive(Debug, serde::Deserialize)] - #[allow(dead_code)] - struct Record { - // deserialize timestamp to chrono::DateTime - ts: DateTime, - // float to f32 - current: Option, - // int to i32 - voltage: Option, - phase: Option, - groupid: i32, - // binary/varchar to String - location: String, - } - - let records: Vec = taos - .query("select * from `meters`") - .await? - .deserialize() - .try_collect() - .await?; - - dbg!(records); - Ok(()) -} +## 6. Testing + +### 6.1 Test Execution + +Before running the test, please add the following configuration to the `taos.cfg` file: + +```text +supportVnodes 256 ``` -### Subscription - -```rust -use std::time::Duration; - -use chrono::{DateTime, Local}; -use taos::*; - -// Query options 2, use deserialization with serde. -#[derive(Debug, serde::Deserialize)] -#[allow(dead_code)] -struct Record { - // deserialize timestamp to chrono::DateTime - ts: DateTime, - // float to f32 - current: Option, - // int to i32 - voltage: Option, - phase: Option, -} - -async fn prepare(taos: Taos) -> anyhow::Result<()> { - let inserted = taos.exec_many([ - // create child table - "CREATE TABLE `d0` USING `meters` TAGS(0, 'Los Angles')", - // insert into child table - "INSERT INTO `d0` values(now - 10s, 10, 116, 0.32)", - // insert with NULL values - "INSERT INTO `d0` values(now - 8s, NULL, NULL, NULL)", - // insert and automatically create table with tags if not exists - "INSERT INTO `d1` USING `meters` TAGS(1, 'San Francisco') values(now - 9s, 10.1, 119, 0.33)", - // insert many records in a single sql - "INSERT INTO `d1` values (now-8s, 10, 120, 0.33) (now - 6s, 10, 119, 0.34) (now - 4s, 11.2, 118, 0.322)", - ]).await?; - assert_eq!(inserted, 6); - Ok(()) -} - -#[tokio::main] -async fn main() -> anyhow::Result<()> { - // std::env::set_var("RUST_LOG", "debug"); - pretty_env_logger::init(); - let dsn = "taos://localhost:6030"; - let builder = TaosBuilder::from_dsn(dsn)?; - - let taos = builder.build()?; - let db = "tmq"; - - // prepare database - taos.exec_many([ - format!("DROP TOPIC IF EXISTS tmq_meters"), - format!("DROP DATABASE IF EXISTS `{db}`"), - format!("CREATE DATABASE `{db}`"), - format!("USE `{db}`"), - // create super table - format!("CREATE TABLE `meters` (`ts` TIMESTAMP, `current` FLOAT, `voltage` INT, `phase` FLOAT)\ - TAGS (`groupid` INT, `location` BINARY(16))"), - // create topic for subscription - format!("CREATE TOPIC tmq_meters with META AS DATABASE {db}") - ]) - .await?; - - let task = tokio::spawn(prepare(taos)); - - tokio::time::sleep(Duration::from_secs(1)).await; - - // subscribe - let tmq = TmqBuilder::from_dsn("taos://localhost:6030/?group.id=test")?; - - let mut consumer = tmq.build()?; - consumer.subscribe(["tmq_meters"]).await?; - - { - let mut stream = consumer.stream(); - - while let Some((offset, message)) = stream.try_next().await? { - // get information from offset - - // the topic - let topic = offset.topic(); - // the vgroup id, like partition id in kafka. - let vgroup_id = offset.vgroup_id(); - println!("* in vgroup id {vgroup_id} of topic {topic}\n"); - - if let Some(data) = message.into_data() { - while let Some(block) = data.fetch_raw_block().await? { - // one block for one table, get table name if needed - let name = block.table_name(); - let records: Vec = block.deserialize().try_collect()?; - println!( - "** table: {}, got {} records: {:#?}\n", - name.unwrap(), - records.len(), - records - ); - } - } - consumer.commit(offset).await?; - } - } - - consumer.unsubscribe().await; - - task.await??; - - Ok(()) -} +After completing the configuration, execute the following command in the project directory to run the test: +```sh +cargo test ``` -## Contribution +### 6.2 Test Case Addition + +Add test cases in the `#[cfg(test)]` module of the corresponding `.rs` file. For synchronous code, use the `#[test]` macro; for asynchronous code, use the `#[tokio::test]` macro. + +### 6.3 Performance Testing + +Performance testing is under development. + +## 7. Submitting Issues + +We welcome the submission of [GitHub Issue](https://github.com/taosdata/taos-connector-rust/issues/new?template=Blank+issue). When submitting, please provide the following information: + +- Description of the problem, whether it must occur, preferably with detailed call stack. +- Rust connector version. +- Connection parameters (no username or password required). +- TDengine server version. + +## 8. Submitting PRs + +We welcome developers to contribute to this project. When submitting PRs, please follow these steps: + +1. Fork this project, refer to ([how to fork a repo](https://docs.github.com/en/get-started/quickstart/fork-a-repo)). +2. Create a new branch from the main branch with a meaningful branch name (`git checkout -b my_branch`). Do not modify the main branch directly. +3. Modify the code, ensure all unit tests pass, and add new unit tests to verify the changes. +4. Push the changes to the remote branch (`git push origin my_branch`). +5. Create a Pull Request on GitHub ([how to create a pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request)). +6. After submitting the PR, if CI passes, you can find your PR on the [codecov](https://app.codecov.io/gh/taosdata/taos-connector-rust/pulls) page to check the test coverage. -Welcome for all contributions. +## 9. References -## License +- [TDengine Official Website](https://www.tdengine.com/) +- [TDengine GitHub](https://github.com/taosdata/TDengine) -Keep same with [TDengine]. +## 10. License -[TDengine]: https://www.taosdata.com/en/getting-started/ -[r2d2]: https://crates.io/crates/r2d2 +[MIT License](./LICENSE)