Skip to main content

Backend

Trait Backend 

Source
pub trait Backend:
    Send
    + Sync
    + 'static {
Show 14 methods // Required methods fn names(&self) -> Vec<String>; fn summary(&self, name: &str) -> Result<DatasetSummary, AppError>; fn schema(&self, name: &str) -> Result<Arc<DatasetSchema>, AppError>; fn sample<'life0, 'life1, 'async_trait>( &'life0 self, name: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<String, AppError>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn query<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, name: &'life1 str, req: &'life2 QueryRequest, ) -> Pin<Box<dyn Future<Output = Result<String, AppError>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait; fn count<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, name: &'life1 str, req: &'life2 CountRequest, ) -> Pin<Box<dyn Future<Output = Result<i64, AppError>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait; fn reload<'life0, 'life1, 'async_trait>( &'life0 self, name: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<ReloadStats, AppError>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; // Provided methods fn indexed_columns(&self, _name: &str) -> Result<Vec<String>, AppError> { ... } fn query_arrow<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _name: &'life1 str, _req: &'life2 QueryRequest, ) -> Pin<Box<dyn Future<Output = Result<Vec<u8>, AppError>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn query_arrow_stream<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, name: &'life1 str, req: &'life2 QueryRequest, ) -> Pin<Box<dyn Future<Output = Result<ArrowIpcStream, AppError>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn query_arrow_stream_all<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, name: &'life1 str, req: &'life2 QueryRequest, ) -> Pin<Box<dyn Future<Output = Result<ArrowIpcStream, AppError>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait { ... } fn query_sql<'life0, 'life1, 'async_trait>( &'life0 self, _sql: &'life1 str, _max_rows: u64, ) -> Pin<Box<dyn Future<Output = Result<String, AppError>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait { ... } fn query_sql_arrow_stream<'life0, 'life1, 'async_trait>( &'life0 self, _sql: &'life1 str, _max_rows: u64, ) -> Pin<Box<dyn Future<Output = Result<ArrowIpcStream, AppError>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait { ... } fn parquet<'life0, 'life1, 'async_trait>( &'life0 self, _name: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<Bytes, AppError>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait { ... }
}
Expand description

Read / reload interface every backend exposes to the HTTP layer.

All methods are async — synchronous backends (DuckDB) wrap their blocking calls in actix_web::web::block inside the impl.

Required Methods§

Source

fn names(&self) -> Vec<String>

Sorted list of dataset names.

Source

fn summary(&self, name: &str) -> Result<DatasetSummary, AppError>

Cheap summary for the dataset listing endpoint. Err(NotFound) on unknown name.

Source

fn schema(&self, name: &str) -> Result<Arc<DatasetSchema>, AppError>

Full schema for name. Err(NotFound) on unknown name.

Source

fn sample<'life0, 'life1, 'async_trait>( &'life0 self, name: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<String, AppError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

JSON for the first row of the dataset, or the literal string "null" if the dataset is empty.

Source

fn query<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, name: &'life1 str, req: &'life2 QueryRequest, ) -> Pin<Box<dyn Future<Output = Result<String, AppError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Execute req against name, returning the JSON-encoded data array (without the {"data": …, "page": …} envelope — that’s added by the handler).

Source

fn count<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, name: &'life1 str, req: &'life2 CountRequest, ) -> Pin<Box<dyn Future<Output = Result<i64, AppError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Count rows in name matching req.predicates.

Source

fn reload<'life0, 'life1, 'async_trait>( &'life0 self, name: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<ReloadStats, AppError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Rebuild name from its configured source and atomically swap it in.

Provided Methods§

Source

fn indexed_columns(&self, _name: &str) -> Result<Vec<String>, AppError>

Names of columns the backend has built an equality index over, for inclusion in the /schema response. Default impl returns an empty vec — backends without per-column indexes (e.g. DuckDB, which relies on the embedded database engine) need not override.

Source

fn query_arrow<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _name: &'life1 str, _req: &'life2 QueryRequest, ) -> Pin<Box<dyn Future<Output = Result<Vec<u8>, AppError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Execute req against name, returning the result as an Arrow IPC stream byte buffer (one schema message + zero or more RecordBatch messages + EOS). The handler ships this verbatim with Content-Type: application/vnd.apache.arrow.stream.

Default impl errors with InvalidValue — backends that don’t produce Arrow natively (e.g. DuckDB today) reject the format and the handler falls through to JSON. Override on backends where batches are already Arrow.

Source

fn query_arrow_stream<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, name: &'life1 str, req: &'life2 QueryRequest, ) -> Pin<Box<dyn Future<Output = Result<ArrowIpcStream, AppError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Execute req and stream the Arrow IPC bytes. The default adapter preserves compatibility for backends that only implement Backend::query_arrow, but high-throughput backends should override this to avoid building one full response buffer.

Source

fn query_arrow_stream_all<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, name: &'life1 str, req: &'life2 QueryRequest, ) -> Pin<Box<dyn Future<Output = Result<ArrowIpcStream, AppError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Execute req and stream all matching Arrow IPC batches in one HTTP response. Unlike Backend::query_arrow_stream, this is not page scoped; limit may still cap the total rows returned.

Source

fn query_sql<'life0, 'life1, 'async_trait>( &'life0 self, _sql: &'life1 str, _max_rows: u64, ) -> Pin<Box<dyn Future<Output = Result<String, AppError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Execute a pre-validated raw SELECT and return the JSON-encoded data array (same shape as Backend::query — the handler adds the {"data": …} envelope).

sql has already passed crate::sql::validate: it is a single read-only query that references only registered datasets. The backend wraps it in an outer LIMIT max_rows before executing so the result size is bounded regardless of the user’s own LIMIT.

Default impl errors with InvalidValue; backends that support raw SQL (DuckDB, DataFusion) override it.

Source

fn query_sql_arrow_stream<'life0, 'life1, 'async_trait>( &'life0 self, _sql: &'life1 str, _max_rows: u64, ) -> Pin<Box<dyn Future<Output = Result<ArrowIpcStream, AppError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Execute a pre-validated raw SELECT and stream the result as Arrow IPC bytes (one schema message + zero or more RecordBatch messages

sql has already passed crate::sql::validate; the backend wraps it in an outer LIMIT max_rows so the result is bounded regardless of the caller’s own clauses. Powers the Arrow content-negotiated branch of POST /api/v1/sql.

Default impl errors with InvalidValue; backends that support raw SQL (DuckDB, DataFusion) override it.

Source

fn parquet<'life0, 'life1, 'async_trait>( &'life0 self, _name: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<Bytes, AppError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Encode the entire dataset as a single self-contained Parquet file, returned as in-memory bytes.

Powers GET /datasets/{name}/parquet, which serves these bytes with HTTP range support so external tools (DuckDB httpfs, pandas, polars, …) can read the dataset straight over HTTP — e.g. SELECT count(*) FROM 'http://host/api/v1/datasets/accidents/parquet'.

The handler caches the result per dataset (and invalidates on reload) so the repeated range requests a Parquet reader makes all see identical, stable bytes. Default impl errors with InvalidValue; every shipped backend overrides it.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§