Skip to content
 
 

Repository files navigation

dameng

Crates.io Docs.rs License: MIT

A pure-Rust driver for Dameng Database (DM8).

中文文档 (Chinese)

Features

  • Pure-Rust protocol — full DM8 binary wire protocol (STARTUP, LOGIN, EXEC, OPE, FETCH, COMMIT, ROLLBACK)
  • SQLx-style parameter binding&[&id, &name] with automatic type conversion
  • Transaction supportTransaction API with automatic rollback on Drop
  • Rich type system — INT, BIGINT, VARCHAR, FLOAT, DOUBLE, DECIMAL, DATE, TIME, TIMESTAMP, BLOB, CLOB, and more
  • Safe — parameterized queries prevent SQL injection
  • TLS support — optional SSL/TLS encrypted connections

Installation

[dependencies]
dameng = "0.1.0"

Quick Start

Connect

use dameng::Client;

let mut client = Client::new("127.0.0.1", 5236);
client.connect("SYSDBA", "SYSDBA")?;

Query

let rs = client.query("SELECT ID, NAME, ADDRESS FROM PERSON")?;
for row in rs.iter() {
    let id: i32 = row.get(0)?;
    let name: &str = row.get(1)?;
    let address: Option<&str> = row.get(2)?;
    println!("ID={}, NAME={}, ADDRESS={:?}", id, name, address);
}

Parameterized Queries (SQLx style)

let id: i32 = 1;
let name: &str = "Alice";
let rs = client.query_with_params(
    "SELECT * FROM PERSON WHERE ID = ? AND NAME = ?",
    &[&id, &name],
)?;

DML (INSERT / UPDATE / DELETE)

let affected = client.execute_with_params(
    "INSERT INTO PERSON (ID, NAME, AGE) VALUES (?, ?, ?)",
    &[&1, &"Alice", &25],
)?;
println!("Inserted {} rows", affected);

Transactions

let mut tx = client.transaction()?;

tx.execute_with_params("INSERT INTO PERSON VALUES (?, ?)", &[&1, &"Alice"])?;
tx.execute_with_params("INSERT INTO PERSON VALUES (?, ?)", &[&2, &"Bob"])?;

tx.commit()?;

All operations within a transaction execute as an atomic unit. If a Transaction is dropped without an explicit commit() or rollback(), a ROLLBACK is sent automatically.

Full CRUD Example

use dameng::Client;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = Client::new("127.0.0.1", 5236);
    client.connect("SYSDBA", "SYSDBA")?;

    // CREATE
    client.execute("CREATE TABLE IF NOT EXISTS users (
        id INT PRIMARY KEY,
        name VARCHAR(100),
        age INT
    )")?;

    // INSERT — batch insert in a transaction
    let mut tx = client.transaction()?;
    let users = [(1, "Alice", 25i32), (2, "Bob", 30), (3, "Carol", 28)];
    for (id, name, age) in &users {
        tx.execute_with_params(
            "INSERT INTO users VALUES (?, ?, ?)",
            &[&id, &name, &age],
        )?;
    }
    tx.commit()?;

    // SELECT
    let rs = client.query_with_params(
        "SELECT name, age FROM users WHERE age > ? ORDER BY age",
        &[&26i32],
    )?;
    for row in rs.iter() {
        let name = row.get_str(0).unwrap_or("<NULL>");
        let age: i32 = row.get(1).unwrap_or_default();
        println!("{name}: {age}");
    }

    // UPDATE
    client.execute_with_params(
        "UPDATE users SET age = ? WHERE id = ?",
        &[&31i32, &1i32],
    )?;

    // DELETE
    client.execute_with_params("DELETE FROM users WHERE id = ?", &[&3i32])?;

    client.close()?;
    Ok(())
}

API Reference

Client

Method Returns Description
Client::new(host, port) Client Create a new client
connect(username, password) Result<()> Connect to the database
close() Result<()> Close the connection
transaction() Result<Transaction> Begin a new transaction
execute(sql) Result<u64> Execute DML, returns affected rows
execute_with_params(sql, params) Result<u64> Execute DML with parameters
query(sql) Result<ResultSet> Execute a SELECT query
query_with_params(sql, params) Result<ResultSet> Execute a SELECT query with parameters
begin() Result<()> Disable auto-commit (low-level)

Transaction

Method Returns Description
commit(self) Result<()> Commit and consume the transaction, releasing the Client
rollback(self) Result<()> Rollback and consume the transaction, releasing the Client
execute(sql) Result<u64> DML within the transaction
execute_with_params(sql, params) Result<u64> DML with parameters within the transaction
query(sql) Result<ResultSet> SELECT within the transaction
query_with_params(sql, params) Result<ResultSet> SELECT with parameters within the transaction

ResultSet

Method / Field Description
iter() Returns an iterator over the rows
columns Column metadata: Vec<Column>
rows Row data: Vec<Row>
total_row_count Total row count reported by the server

QueryRow

Method Description
get::<T>(idx) Get a column value by type (recommended)
get_i32(idx) / get_i64(idx) Get an integer value
get_str(idx) Get a string value
get_f64(idx) Get a float value
get_opt_str(idx) Get an optional string (NULL-safe)

Type Mapping

Rust Type DM Type ToDmValue
i8 TINYINT DmValue::TinyInt
i16 SMALLINT DmValue::SmallInt
i32 INT DmValue::Int
i64 BIGINT DmValue::BigInt
f32 FLOAT DmValue::Float
f64 DOUBLE DmValue::Double
bool BIT DmValue::Boolean
&str / String VARCHAR DmValue::Text
Vec<u8> VARBINARY DmValue::Bytea
rust_decimal::Decimal DECIMAL
chrono::NaiveDate DATE
chrono::NaiveDateTime TIMESTAMP

Connection Configuration

use dameng::{Client, ConnectOptions, IsolationLevel};

// Via DSN
let opts = ConnectOptions::from_dsn(
    "dm://SYSDBA:SYSDBA@127.0.0.1:5236/?auto_commit=false&isolation_level=serializable"
)?;
let mut client = Client::connect_with(&opts)?;

// Or manually
let mut client = Client::new("127.0.0.1", 5236);
client.auto_commit = false;
client.isolation_level = IsolationLevel::Serializable;
client.connect("SYSDBA", "SYSDBA")?;

License

MIT

About

达梦数据库 Rust 驱动

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages