Skip to main content

Crate dbcli

Crate dbcli 

Source
Expand description

§dbcli

A utility library that automatically converts SQL query results (sqlx Row) into serde_json::Value without requiring struct mappings.

Supports generating JSON arrays directly from database query results, eliminating the need to define structs manually. Suitable for dynamic queries, report exports, and generic API scenarios.

§Supported Databases

DatabaseFeature flag
MySQLmysql
PostgreSQLpostgres
SQLitesqlite
ODBCodbc

§Feature Flags

Enable the corresponding feature in Cargo.toml as needed:

[dependencies]
dbcli = { path = "...", features = ["postgres"] }
# Or enable multiple features at once
dbcli = { path = "...", features = ["mysql", "sqlite"] }

Each feature automatically pulls in the corresponding sqlx driver and dependencies such as chrono and rust_decimal:

  • mysql / postgres: includes chrono, rust_decimal, base64, encoding_rs
  • sqlite: includes only base64 (SQLite dates are stored as TEXT, no chrono needed)
  • odbc: includes odbc-api, base64, encoding_rs, tokio (requires system unixODBC)

§Quick Usage Example

use sqlx::PgPool;

async fn query_to_json(pool: &PgPool) -> anyhow::Result<()> {
    use dbcli::to_json::postgres::to_json;

    let rows = sqlx::query("SELECT id, name, created_at FROM users")
        .fetch_all(pool)
        .await?;

    // data: Vec<serde_json::Value>, each element is a JSON object for one row
    // columns: Vec<ColumnBaseInfo>, containing column name, type, and index info
    let (data, columns) = to_json(rows)?;
    println!("{}", serde_json::to_string_pretty(&data)?);
    Ok(())
}

§Custom Parsing Example

By implementing the to_json::ToJsonCustomizer trait, you can override the default conversion logic for specific types:

use dbcli::to_json::{ToJsonCustomizer, set_to_json_customizer};

struct MyCustomizer;

impl ToJsonCustomizer for MyCustomizer {
    #[cfg(feature = "postgres")]
    fn customize_pg(
        &self,
        type_name: &str,
    ) -> Option<fn(&sqlx::postgres::PgRow, usize) -> serde_json::Value> {
        match type_name {
            // Format TIMESTAMP as ISO 8601
            "TIMESTAMP" => Some(|row, idx| {
                use sqlx::Row;
                use chrono::NaiveDateTime;
                match row.try_get::<Option<NaiveDateTime>, _>(idx) {
                    Ok(Some(dt)) => serde_json::Value::String(
                        dt.format("%Y-%m-%dT%H:%M:%S").to_string()
                    ),
                    _ => serde_json::Value::Null,
                }
            }),
            _ => None,
        }
    }
}

// Register globally once at application startup
fn init() {
    set_to_json_customizer(Box::new(MyCustomizer));
}

Re-exports§

pub use sql_result::SqlResult;

Modules§

column_info
decode
execute
Execute arbitrary SQL statements and automatically parse results.
sql_result
to_json
to_json Module

Macros§

impl_to_json
Generic row-to-JSON macro that eliminates duplicated to_json boilerplate across all three driver files.