Skip to content
ScopeDB Docs
ScopeDB Docs

Rust SDK

On this page

Use the async Rust SDK from trusted backend applications and services.

Before you start

Use Rust 1.85 or later. Follow Connect an application, then set the endpoint and API key used by the examples:

export SCOPEDB_ENDPOINT="https://<endpoint>"
export SCOPEDB_API_KEY="<api-key>"

Install

cargo add scopedb-client serde_json
cargo add tokio --features macros,rt-multi-thread

Create a client

The SDK accepts a configured HTTP client. Use the compatible reqwest version re-exported by scopedb-client to configure authentication, TLS, timeouts, and connection pooling:

use scopedb_client::Client;
use scopedb_client::reqwest;
use scopedb_client::reqwest::header::{AUTHORIZATION, HeaderMap, HeaderValue};

let endpoint = std::env::var("SCOPEDB_ENDPOINT")?;
let api_key = std::env::var("SCOPEDB_API_KEY")?;

let mut authorization = HeaderValue::from_str(&format!("Bearer {api_key}"))?;
authorization.set_sensitive(true);

let mut headers = HeaderMap::new();
headers.insert(AUTHORIZATION, authorization);

let http_client = reqwest::Client::builder()
    .default_headers(headers)
    .build()?;
let client = Client::new(endpoint, http_client)?;

Marking the authorization header as sensitive prevents standard header and request Debug formatting from exposing the API key.

Execute a statement

let result = client
    .statement(
        r#"
        FROM events
        WHERE service = 'checkout'
        ORDER BY time DESC
        LIMIT 10
        "#
        .to_string(),
    )
    .execute()
    .await?;

execute() waits for a terminal result and returns an error when execution fails or is cancelled.

Work with results

Convert result cells to typed Rust values:

let fields = result.schema().fields();
println!("{} columns", fields.len());

let rows = result.into_values()?;
println!("{rows:?}");

Use json_rows() when the application needs unconverted string cell values instead of typed SDK values. See the data types reference for ScopeDB type semantics.

Control statement execution

Use submit() when you need a statement handle instead of waiting through execute():

let mut handle = client.statement("SELECT 1 AS ok".to_string()).submit().await?;

println!("status: {:?}", handle.status());
handle.fetch_once().await?;
let result = handle.fetch().await?;

Dropping the future stops client-side waiting; it does not cancel the remote statement. Call handle.cancel().await to request server-side cancellation. See the HTTP API for the underlying lifecycle and error contract.

Browse the catalog

List methods return one page and preserve the opaque continuation token. Fetch methods return a complete database, schema, or table resource:

use scopedb_client::CatalogListOptions;

let tables = client
    .list_tables("scopedb", "public", CatalogListOptions::default())
    .await?;
let table = client.fetch_table("scopedb", "public", "events").await?;

println!("{} tables; selected {}", tables.items.len(), table.name);

Stream JSON rows to a table

Use append_stream() to write rows to an existing table. Send each row with send(), then call shutdown() when you have finished. The SDK groups rows into batches automatically.

let stream = client
    .table("events")
    .with_schema("public")
    .append_stream()
    .build()?;

stream
    .send(&serde_json::json!({
        "service": "checkout",
        "name": "request.completed",
    }))
    .await?;

let report = stream.shutdown().await?;
println!("wrote {} rows", report.committed_rows);

send() adds a row to the SDK's buffer. shutdown() sends the remaining rows, waits for the writes to finish, and closes the stream. The ? operator returns any write error to the caller.

Use flush() when you want to wait for pending writes and then keep using the same stream. See the Rust SDK examples for bulk writes and logging.

Next steps