Apache IoTDB provides an official Rust client SDK: apache/iotdb-client-rust. It speaks the Thrift RPC protocol (default port 6667) and supports both IoTDB data models:
Session / SessionPool: device/timeseries paths (root.sg.d1.s1), covered in this documentTableSession / TableSessionPool: relational SQL dialectOnce published to crates.io:
[dependencies] iotdb-client-rust = "0.1"
Until then, use a git dependency:
[dependencies] iotdb-client = { git = "https://github.com/apache/iotdb-client-rust" }
The import name is iotdb_client in both cases.
use iotdb_client::{Result, Session, SessionConfig, TSDataType, Tablet, Value}; fn main() -> Result<()> { let config = SessionConfig::default().with_node_urls(&["127.0.0.1:6667"])?; let mut session = Session::new(config); session.open()?; session.execute_non_query("CREATE DATABASE root.demo")?; session.execute_non_query( "CREATE TIMESERIES root.demo.d1.temperature WITH DATATYPE=DOUBLE, ENCODING=PLAIN", )?; // Batch write via a column-major tablet (nulls allowed). let mut tablet = Tablet::new( "root.demo.d1", vec!["temperature".into()], vec![TSDataType::Double], )?; tablet.add_row(1_720_000_000_000, vec![Some(Value::Double(21.5))])?; tablet.add_row(1_720_000_001_000, vec![None])?; // null cell session.insert_tablet(&tablet)?; // Or write a single row via insertRecord (aligned variants and // multi-row insert_records / insert_records_of_one_device also exist). session.insert_record( "root.demo.d1", 1_720_000_002_000, vec!["temperature".into()], &[Value::Double(22.0)], false, // is_aligned )?; // Query with row iteration; the dataset borrows the session until dropped. { let mut dataset = session.execute_query("SELECT temperature FROM root.demo.d1")?; while let Some(row) = dataset.next_row()? { println!("ts={:?} values={:?}", row.timestamp, row.values); } } session.execute_non_query("DELETE DATABASE root.demo")?; session.close() }
SessionPool is a thread-safe pool for concurrent workloads. acquire() returns an RAII guard that releases the session back to the pool on drop:
use std::sync::Arc; use iotdb_client::{Result, SessionPool, SessionPoolConfig}; fn main() -> Result<()> { let config = SessionPoolConfig { max_size: 4, ..SessionPoolConfig::default() } .with_node_urls(&["127.0.0.1:6667"])?; let pool = Arc::new(SessionPool::new(config)?); let handles: Vec<_> = (0..4) .map(|_| { let pool = Arc::clone(&pool); std::thread::spawn(move || -> Result<()> { let mut session = pool.acquire()?; session.execute_non_query("SHOW DATABASES")?; Ok(()) }) }) .collect(); for handle in handles { handle.join().expect("thread panicked")?; } pool.close(); Ok(()) }
RPC compression (the Thrift compact protocol) must match the server setting dn_rpc_thrift_compression_enable (default false):
let config = SessionConfig { enable_rpc_compression: true, ..Default::default() };
TLS is behind the tls cargo feature:
iotdb-client-rust = { version = "0.1", features = ["tls"] }
let config = SessionConfig { use_ssl: true, ca_cert_path: Some("ca.pem".into()), // trust a private CA / self-signed cert accept_invalid_certs: false, // true skips verification (tests only!) domain_override: None, // SNI/validation hostname when connecting by IP ..Default::default() };
Full runnable examples live in the repository's examples/ directory:
cargo run --example tree_session cargo run --example table_session cargo run --example session_pool