Skip to content

Commit

Permalink
docs: modify README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
qevolg committed Jan 24, 2025
1 parent 8833c06 commit cabffbc
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 213 deletions.
4 changes: 2 additions & 2 deletions README-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ cargo build

### 6.1 运行测试

运行测试前,请在 `/etc/taos/taos.cfg` 文件中添加以下配置:
运行测试前,请在 `taos.cfg` 文件中添加以下配置:

```text
supportVnodes 256
Expand Down Expand Up @@ -122,7 +122,7 @@ cargo test
3. 开发与测试:完成代码修改后,确保所有单元测试都能通过,并为新增功能或修复的 Bug 添加相应的测试用例。
4. 提交代码:将修改提交到远程分支(例如:`git push origin feature/my_feature`)。
5. 创建 Pull Request:在 GitHub 上发起 [Pull Request](https://github.com/taosdata/taos-connector-rust/pulls),具体步骤请参考 [如何创建 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. 检查 CI 和代码覆盖率:提交 PR 后,确保 CI 流程通过。您可以在 [Codecov 页面](https://app.codecov.io/gh/taosdata/taos-connector-rust/pulls) 查看对应 PR 的代码覆盖率。
6. 检查 CI 和代码覆盖率:提交 PR 后,确保 CI 流程通过。您可以在 [Codecov](https://app.codecov.io/gh/taosdata/taos-connector-rust/pulls) 查看对应 PR 的代码覆盖率。

感谢您的贡献!我们期待与您共同完善和优化该项目。

Expand Down
317 changes: 106 additions & 211 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,241 +1,136 @@
# The Official Rust Connector for [TDengine]
<!-- omit in toc -->
# TDengine Rust Connector
<!-- omit in toc -->

| 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
<!-- omit in toc -->
## Table of Contents
<!-- omit in toc -->

- [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

- 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.

For websocket client only:
## 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<Local>
ts: DateTime<Local>,
// float to f32
current: Option<f32>,
// int to i32
voltage: Option<i32>,
phase: Option<f32>,
groupid: i32,
// binary/varchar to String
location: String,
}

let records: Vec<Record> = 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<Local>
ts: DateTime<Local>,
// float to f32
current: Option<f32>,
// int to i32
voltage: Option<i32>,
phase: Option<f32>,
}

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<Record> = 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 you to submit [GitHub Issue](https://github.com/taosdata/taos-connector-rust/issues/new?template=Blank+issue). Please provide the following information when submitting so that we can quickly locate the problem:

- Problem description: The specific problem manifestation and whether it must occur. It is recommended to attach detailed call stack or log information.
- Rust connector version: The version number can be obtained through `Cargo.toml` or `cargo metadata`.
- Connection parameters: Provide key connection parameters (no need to include username and password).
- TDengine server version: The version information can be obtained through `select server_version()`.

If you have other relevant information (such as environment configuration, operating system version, etc.), please add it so that we can have a more comprehensive understanding of the problem.

## 8. Submitting PRs

We welcome developers to participate in the development of this project. Please follow the steps below when submitting a PR:

1. Fork the repository: Please fork this repository first. For specific steps, please refer to [How to Fork a Repo](https://docs.github.com/en/get-started/quickstart/fork-a-repo).
2. Create a new branch: Create a new branch based on the `main` branch and use a meaningful branch name (for example: `git checkout -b feature/my_feature`). Do not modify it directly on the main branch.
3. Development and testing: After completing the code modification, make sure that all unit tests pass, and add corresponding test cases for new features or fixed bugs.
4. Submit code: Submit the changes to the remote branch (for example: `git push origin feature/my_feature`).
5. Create a Pull Request: Initiate a Pull Request on GitHub. For specific steps, please refer to [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. Check CI and code coverage: After submitting the PR, make sure the CI process passes. You can check the code coverage of the corresponding PR on the [Codecov](https://app.codecov.io/gh/taosdata/taos-connector-rust/pulls).

Thank you for your contribution! We look forward to working with you to improve and optimize the project.

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)

0 comments on commit cabffbc

Please sign in to comment.