{"id":19381790,"url":"https://github.com/taosdata/taos-connector-rust","last_synced_at":"2025-04-23T20:32:06.145Z","repository":{"id":55063848,"uuid":"522848088","full_name":"taosdata/taos-connector-rust","owner":"taosdata","description":"TDengine connector for Rust","archived":false,"fork":false,"pushed_at":"2025-04-18T01:26:44.000Z","size":13772,"stargazers_count":35,"open_issues_count":3,"forks_count":15,"subscribers_count":21,"default_branch":"main","last_synced_at":"2025-04-18T01:54:37.714Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/taosdata.png","metadata":{"files":{"readme":"README-CN.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-08-09T07:32:32.000Z","updated_at":"2025-04-17T12:20:10.000Z","dependencies_parsed_at":"2023-10-17T07:11:20.662Z","dependency_job_id":"fce0099a-eb33-4c6d-bdc1-99ad81469e35","html_url":"https://github.com/taosdata/taos-connector-rust","commit_stats":{"total_commits":422,"total_committers":8,"mean_commits":52.75,"dds":0.1255924170616114,"last_synced_commit":"1152847729afe717886b2043141610f3444138b7"},"previous_names":[],"tags_count":689,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taosdata%2Ftaos-connector-rust","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taosdata%2Ftaos-connector-rust/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taosdata%2Ftaos-connector-rust/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/taosdata%2Ftaos-connector-rust/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/taosdata","download_url":"https://codeload.github.com/taosdata/taos-connector-rust/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250509734,"owners_count":21442486,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-10T09:18:24.191Z","updated_at":"2025-04-23T20:32:01.133Z","avatar_url":"https://github.com/taosdata.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# The Official Rust Connector for [TDengine]\n\n| Docs.rs                                        | Crates.io Version                                  | Crates.io Downloads                                | CodeCov                                                                                                                                                           |\n| ---------------------------------------------- | -------------------------------------------------- | -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| ![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) |\n\nThis is the official TDengine connector in Rust.\n\n## Dependencies\n\n- [Rust](https://www.rust-lang.org/learn/get-started) of course.\n\nif you use the default features, it'll depend on:\n\n- [TDengine] Client library and headers.\n\n## Usage\n\nBy default, enable both native and websocket client:\n\n```toml\n[dependencies]\ntaos = \"*\"\n```\n\nFor websocket client only:\n\n```toml\n[dependencies]\ntaos = { version = \"*\", default-features = false, features = [\"ws\"] }\n```\n\nFor native only:\n\n```toml\n[dependencies]\ntaos = { version = \"*\", default-features = false, features = [\"native\"] }\n```\n\n### Query\n\n```rust\nuse chrono::{DateTime, Local};\nuse taos::*;\n\n#[tokio::main]\nasync fn main() -\u003e anyhow::Result\u003c()\u003e {\n    let dsn = \"taos://localhost:6030\";\n    let builder = TaosBuilder::from_dsn(dsn)?;\n\n    let taos = builder.build()?;\n\n    let db = \"query\";\n\n    // prepare database\n    taos.exec_many([\n        format!(\"DROP DATABASE IF EXISTS `{db}`\"),\n        format!(\"CREATE DATABASE `{db}`\"),\n        format!(\"USE `{db}`\"),\n    ])\n    .await?;\n\n    let inserted = taos.exec_many([\n        // create super table\n        \"CREATE TABLE `meters` (`ts` TIMESTAMP, `current` FLOAT, `voltage` INT, `phase` FLOAT) \\\n         TAGS (`groupid` INT, `location` BINARY(16))\",\n        // create child table\n        \"CREATE TABLE `d0` USING `meters` TAGS(0, 'Los Angles')\",\n        // insert into child table\n        \"INSERT INTO `d0` values(now - 10s, 10, 116, 0.32)\",\n        // insert with NULL values\n        \"INSERT INTO `d0` values(now - 8s, NULL, NULL, NULL)\",\n        // insert and automatically create table with tags if not exists\n        \"INSERT INTO `d1` USING `meters` TAGS(1, 'San Francisco') values(now - 9s, 10.1, 119, 0.33)\",\n        // insert many records in a single sql\n        \"INSERT INTO `d1` values (now-8s, 10, 120, 0.33) (now - 6s, 10, 119, 0.34) (now - 4s, 11.2, 118, 0.322)\",\n    ]).await?;\n\n    assert_eq!(inserted, 6);\n    let mut result = taos.query(\"select * from `meters`\").await?;\n\n    for field in result.fields() {\n        println!(\"got field: {}\", field.name());\n    }\n\n    // Query option 1, use rows stream.\n    let mut rows = result.rows();\n    while let Some(row) = rows.try_next().await? {\n        for (name, value) in row {\n            println!(\"got value of {}: {}\", name, value);\n        }\n    }\n\n    // Query options 2, use deserialization with serde.\n    #[derive(Debug, serde::Deserialize)]\n    #[allow(dead_code)]\n    struct Record {\n        // deserialize timestamp to chrono::DateTime\u003cLocal\u003e\n        ts: DateTime\u003cLocal\u003e,\n        // float to f32\n        current: Option\u003cf32\u003e,\n        // int to i32\n        voltage: Option\u003ci32\u003e,\n        phase: Option\u003cf32\u003e,\n        groupid: i32,\n        // binary/varchar to String\n        location: String,\n    }\n\n    let records: Vec\u003cRecord\u003e = taos\n        .query(\"select * from `meters`\")\n        .await?\n        .deserialize()\n        .try_collect()\n        .await?;\n\n    dbg!(records);\n    Ok(())\n}\n```\n\n### Subscription\n\n```rust\nuse std::time::Duration;\n\nuse chrono::{DateTime, Local};\nuse taos::*;\n\n// Query options 2, use deserialization with serde.\n#[derive(Debug, serde::Deserialize)]\n#[allow(dead_code)]\nstruct Record {\n    // deserialize timestamp to chrono::DateTime\u003cLocal\u003e\n    ts: DateTime\u003cLocal\u003e,\n    // float to f32\n    current: Option\u003cf32\u003e,\n    // int to i32\n    voltage: Option\u003ci32\u003e,\n    phase: Option\u003cf32\u003e,\n}\n\nasync fn prepare(taos: Taos) -\u003e anyhow::Result\u003c()\u003e {\n    let inserted = taos.exec_many([\n        // create child table\n        \"CREATE TABLE `d0` USING `meters` TAGS(0, 'Los Angles')\",\n        // insert into child table\n        \"INSERT INTO `d0` values(now - 10s, 10, 116, 0.32)\",\n        // insert with NULL values\n        \"INSERT INTO `d0` values(now - 8s, NULL, NULL, NULL)\",\n        // insert and automatically create table with tags if not exists\n        \"INSERT INTO `d1` USING `meters` TAGS(1, 'San Francisco') values(now - 9s, 10.1, 119, 0.33)\",\n        // insert many records in a single sql\n        \"INSERT INTO `d1` values (now-8s, 10, 120, 0.33) (now - 6s, 10, 119, 0.34) (now - 4s, 11.2, 118, 0.322)\",\n    ]).await?;\n    assert_eq!(inserted, 6);\n    Ok(())\n}\n\n#[tokio::main]\nasync fn main() -\u003e anyhow::Result\u003c()\u003e {\n    // std::env::set_var(\"RUST_LOG\", \"debug\");\n    pretty_env_logger::init();\n    let dsn = \"taos://localhost:6030\";\n    let builder = TaosBuilder::from_dsn(dsn)?;\n\n    let taos = builder.build()?;\n    let db = \"tmq\";\n\n    // prepare database\n    taos.exec_many([\n        format!(\"DROP TOPIC IF EXISTS tmq_meters\"),\n        format!(\"DROP DATABASE IF EXISTS `{db}`\"),\n        format!(\"CREATE DATABASE `{db}`\"),\n        format!(\"USE `{db}`\"),\n        // create super table\n        format!(\"CREATE TABLE `meters` (`ts` TIMESTAMP, `current` FLOAT, `voltage` INT, `phase` FLOAT)\\\n                 TAGS (`groupid` INT, `location` BINARY(16))\"),\n        // create topic for subscription\n        format!(\"CREATE TOPIC tmq_meters with META AS DATABASE {db}\")\n    ])\n    .await?;\n\n    let task = tokio::spawn(prepare(taos));\n\n    tokio::time::sleep(Duration::from_secs(1)).await;\n\n    // subscribe\n    let tmq = TmqBuilder::from_dsn(\"taos://localhost:6030/?group.id=test\")?;\n\n    let mut consumer = tmq.build()?;\n    consumer.subscribe([\"tmq_meters\"]).await?;\n\n    {\n        let mut stream = consumer.stream();\n\n        while let Some((offset, message)) = stream.try_next().await? {\n            // get information from offset\n\n            // the topic\n            let topic = offset.topic();\n            // the vgroup id, like partition id in kafka.\n            let vgroup_id = offset.vgroup_id();\n            println!(\"* in vgroup id {vgroup_id} of topic {topic}\\n\");\n\n            if let Some(data) = message.into_data() {\n                while let Some(block) = data.fetch_raw_block().await? {\n                    // one block for one table, get table name if needed\n                    let name = block.table_name();\n                    let records: Vec\u003cRecord\u003e = block.deserialize().try_collect()?;\n                    println!(\n                        \"** table: {}, got {} records: {:#?}\\n\",\n                        name.unwrap(),\n                        records.len(),\n                        records\n                    );\n                }\n            }\n            consumer.commit(offset).await?;\n        }\n    }\n\n    consumer.unsubscribe().await;\n\n    task.await??;\n\n    Ok(())\n}\n\n```\n\n## Contribution\n\nWelcome for all contributions.\n\n## License\n\nKeep same with [TDengine].\n\n[TDengine]: https://www.taosdata.com/en/getting-started/\n[r2d2]: https://crates.io/crates/r2d2\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftaosdata%2Ftaos-connector-rust","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftaosdata%2Ftaos-connector-rust","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftaosdata%2Ftaos-connector-rust/lists"}