pub struct Store { /* private fields */ }Expand description
Multi-dataset registry. Each dataset is registered in the shared
SessionContext under its configured name. The per-dataset state is
held behind ArcSwap so a reload can atomically replace it without
blocking concurrent queries.
Implementations§
Source§impl Store
impl Store
Sourcepub async fn load(cfg: &AppConfig) -> Result<Self, AppError>
pub async fn load(cfg: &AppConfig) -> Result<Self, AppError>
Load every dataset declared in cfg.
pub fn dataset(&self, name: &str) -> Result<Arc<DatasetState>, AppError>
Sourcepub async fn sample(&self, name: &str) -> Result<String, AppError>
pub async fn sample(&self, name: &str) -> Result<String, AppError>
JSON for the first row of the dataset, or null if empty. Used by
GET /api/datasets/{name}/schema for discoverability.
Sourcepub async fn reload(&self, name: &str) -> Result<ReloadStats, AppError>
pub async fn reload(&self, name: &str) -> Result<ReloadStats, AppError>
Rebuild name from disk and atomically swap it in. Concurrent queries
against the same name continue to see the old Arc<DatasetState>
until they finish; the old data is dropped once the last reference
goes away.
Sourcepub async fn query(
&self,
name: &str,
req: &QueryRequest,
) -> Result<String, AppError>
pub async fn query( &self, name: &str, req: &QueryRequest, ) -> Result<String, AppError>
Run a QueryRequest against name. Empty predicates → O(1) Arrow
slice. Otherwise → DataFusion SQL on the single registered table.
Lazy datasets skip the in-memory hot paths and always dispatch to SQL.
Sourcepub async fn query_sql(
&self,
sql: &str,
max_rows: u64,
) -> Result<String, AppError>
pub async fn query_sql( &self, sql: &str, max_rows: u64, ) -> Result<String, AppError>
Execute a pre-validated raw SELECT and return the JSON data
array. The statement has already passed
datapress_core::sql::validate; here it is wrapped in an outer
LIMIT max_rows so the result is bounded regardless of the user’s
own clauses, executed through the shared SessionContext, and run
through the same fast JSON encoder as Self::query.
Sourcepub async fn query_sql_arrow_stream(
&self,
sql: &str,
max_rows: u64,
) -> Result<ArrowIpcStream, AppError>
pub async fn query_sql_arrow_stream( &self, sql: &str, max_rows: u64, ) -> Result<ArrowIpcStream, AppError>
Same plan as Self::query_sql, but encode the bounded result as
an Arrow IPC stream instead of JSON. Backs the Arrow
content-negotiated branch of POST /api/v1/sql.
Sourcepub async fn query_arrow(
&self,
name: &str,
req: &QueryRequest,
) -> Result<Vec<u8>, AppError>
pub async fn query_arrow( &self, name: &str, req: &QueryRequest, ) -> Result<Vec<u8>, AppError>
Same plan as Self::query, but encode the result page as an
Arrow IPC stream (one schema message + one batch + EOS). Empty
results still produce a valid, self-describing zero-batch stream.
pub async fn query_arrow_stream( &self, name: &str, req: &QueryRequest, ) -> Result<ArrowIpcStream, AppError>
pub async fn query_arrow_stream_all( &self, name: &str, req: &QueryRequest, ) -> Result<ArrowIpcStream, AppError>
Sourcepub async fn parquet(&self, name: &str) -> Result<Bytes, AppError>
pub async fn parquet(&self, name: &str) -> Result<Bytes, AppError>
Encode the entire dataset as a single self-contained Parquet file.
Collects every row (all columns, no predicates, no paging) and runs
it through a single parquet::arrow::ArrowWriter, so the result
carries the row-group + footer metadata a Parquet reader needs to
answer count(*) straight from the footer. Powers the cached
GET /datasets/{name}/parquet HTTP endpoint.
Trait Implementations§
Source§impl Backend for Store
impl Backend for Store
Source§fn summary(&self, name: &str) -> Result<DatasetSummary, AppError>
fn summary(&self, name: &str) -> Result<DatasetSummary, AppError>
Err(NotFound)
on unknown name.Source§fn schema(&self, name: &str) -> Result<Arc<DatasetSchema>, AppError>
fn schema(&self, name: &str) -> Result<Arc<DatasetSchema>, AppError>
name. Err(NotFound) on unknown name.Source§fn indexed_columns(&self, name: &str) -> Result<Vec<String>, AppError>
fn indexed_columns(&self, name: &str) -> Result<Vec<String>, AppError>
/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 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 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,
"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,
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,
req against name, returning the JSON-encoded data
array (without the {"data": …, "page": …} envelope — that’s
added by the handler).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,
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,
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. Read moreSource§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<'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,
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,
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,
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 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 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,
name matching req.predicates.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,
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,
SELECT and return the JSON-encoded
data array (same shape as Backend::query — the handler adds
the {"data": …} envelope). Read moreSource§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 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,
SELECT and stream the result as Arrow
IPC bytes (one schema message + zero or more RecordBatch messages Read moreSource§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,
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,
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,
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,
name from its configured source and atomically swap it in.Auto Trait Implementations§
impl !Freeze for Store
impl !RefUnwindSafe for Store
impl !UnwindSafe for Store
impl Send for Store
impl Sync for Store
impl Unpin for Store
impl UnsafeUnpin for Store
Blanket Implementations§
Source§impl<T> AsAny for T
impl<T> AsAny for T
Source§fn any_ref(&self) -> &(dyn Any + Sync + Send + 'static)
fn any_ref(&self) -> &(dyn Any + Sync + Send + 'static)
dyn Any reference to the object: Read moreSource§fn as_any(self: Arc<T>) -> Arc<dyn Any + Sync + Send> ⓘ
fn as_any(self: Arc<T>) -> Arc<dyn Any + Sync + Send> ⓘ
Arc<dyn Any> reference to the object: Read moreSource§fn into_any(self: Box<T>) -> Box<dyn Any + Sync + Send>
fn into_any(self: Box<T>) -> Box<dyn Any + Sync + Send>
Box<dyn Any>: Read moreSource§fn type_name(&self) -> &'static str
fn type_name(&self) -> &'static str
std::any::type_name, since Any does not provide it and
Any::type_id is useless as a debugging aid (its Debug is just a mess of hex digits).Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more