Skip to main content

storage_kit/database/
mod.rs

1//! Collection storage, retrieval, and index request/response types.
2//!
3//! Open a supplied [`crate::Database`] with [`config::DatabaseConfig`] and
4//! import [`crate::DatabaseBackend`] to execute requests. [`catalog`] owns
5//! collections and schema evolution, [`data`] owns records and mutations,
6//! [`query`] owns search, and [`index`] owns index lifecycle. [`StorageLocator`]
7//! is a logical address, not a native connection configuration.
8//!
9//! Optional [`CapabilitySet`] bits are hints about retained operation families;
10//! each call validates the actual request and may reject unsupported options.
11//! Database writes do not share the transactional guarantees of
12//! [`crate::StateStore`].
13
14//! # Write and filter a local collection
15//!
16//! This executable example uses a tiny process-local LanceDB collection. Logical
17//! identity lives in an application field: this LanceDB adapter does not support
18//! portable `DataRecord.id` or ID lookup. Query and index operations have separate
19//! request types; optional capabilities never guarantee every request is supported.
20//!
21//! ```
22//! use storage_kit::{Database, DatabaseBackend};
23//! use storage_kit::database::{StorageLocator, config::{DatabaseConfig, LanceConfig}};
24//! use storage_kit::database::catalog::{CatalogRequest, CreateCollectionMode, CreateCollectionRequest};
25//! use storage_kit::database::data::{DataRecord, DataRequest, DataResponse, DeleteRequest,
26//!     FilterExpr, InsertRequest, ScanRequest, CountRequest, Projection};
27//! # tokio::runtime::Runtime::new()?.block_on(async {
28//! let database = Database::connect(DatabaseConfig::lance(LanceConfig::embedded_path("memory://"))).await?;
29//! let collection = StorageLocator::new("articles");
30//! let first = DataRecord::without_id().field("article", "intro")?.field("title", "Introduction")?
31//!     .field("published", true)?;
32//! database.catalog(CatalogRequest::CreateCollection(CreateCollectionRequest {
33//!     locator: collection.clone(), schema: None, records: vec![first],
34//!     mode: CreateCollectionMode::Create,
35//! })).await?;
36//! database.data(DataRequest::Insert(InsertRequest::append(collection.clone(), vec![
37//!     DataRecord::without_id().field("article", "draft")?
38//!         .field("title", "Draft")?.field("published", false)?,
39//! ]))).await?;
40//! let page = database.data(DataRequest::Scan(ScanRequest {
41//!     locator: collection.clone(), filter: Some(FilterExpr::eq("published", true)),
42//!     projection: Projection::Columns(vec!["title".into()]), limit: Some(10),
43//!     offset: None, page_token: None,
44//! })).await?;
45//! let DataResponse::Records(page) = page else { panic!("scan returns records") };
46//! assert_eq!(page.records.len(), 1);
47//! assert_eq!(page.records[0].fields["title"], "Introduction");
48//!
49//! database.data(DataRequest::Delete(DeleteRequest {
50//!     locator: collection.clone(), filter: FilterExpr::eq("published", false),
51//! })).await?;
52//! assert!(matches!(database.data(DataRequest::Count(CountRequest {
53//!     locator: collection.clone(), filter: None,
54//! })).await?, DataResponse::Count(1)));
55//! database.catalog(CatalogRequest::DropCollection {
56//!     locator: collection, ignore_missing: false,
57//! }).await?;
58//! drop(database);
59//! # Ok::<(), storage_kit::StorageError>(())
60//! # })?;
61//! # Ok::<(), Box<dyn std::error::Error>>(())
62//! ```
63//!
64//! For vector retrieval, build a [`query::NearestRequest`] and inspect each
65//! [`query::ScoredRecord::score_kind`] before interpreting its score. Vector
66//! queries do not require a trained vector index. Index creation and readiness
67//! are separate operations; see [`crate::DatabaseBackend::index`] and
68//! [`index::WaitForIndexRequest`]. Unsupported kinds or options fail explicitly.
69//!
70//! Database has no multi-operation transaction or explicit shutdown method. A
71//! failed ordinary write can have an uncertain outcome; reconcile before replaying.
72//! Drop all owners before removing a caller-owned directory. For control-plane
73//! atomicity, use the separate [StateStore transaction workflow](crate::state).
74
75/// Built-in database construction data.
76///
77/// Constructors build configuration without I/O. Validation and connection
78/// reject invalid settings; [`crate::Database::connect`] opens the selected
79/// backend.
80pub mod config {
81    pub use crate::credentials::Password;
82    pub use crate::databases::config::{
83        CommonConfig, DatabaseConfig, LanceConfig, SurrealConfig, SurrealModeConfig,
84    };
85}
86
87/// Portable collection catalog and schema alteration.
88///
89/// Execute [`CatalogRequest`](crate::database::catalog::CatalogRequest) through [`crate::DatabaseBackend::catalog`].
90/// Catalog overwrite recreates the collection; replacing records while keeping
91/// its schema and indexes belongs to [`WriteMode::Overwrite`](crate::database::data::WriteMode::Overwrite).
92pub mod catalog {
93    pub use crate::core::{
94        AddColumnsRequest, AlterColumnsRequest, CatalogRequest, CatalogResponse, CollectionInfo,
95        CollectionSchema, ColumnAlterationSpec, ComputedColumn, CreateCollectionMode,
96        CreateCollectionRequest, DropColumnsRequest, FieldSchema, FieldType,
97        ListCollectionsRequest, SchemaEvolutionRequest, VectorElementType,
98    };
99}
100
101/// Portable records and data mutations.
102///
103/// Execute [`DataRequest`](crate::database::data::DataRequest) through [`crate::DatabaseBackend::data`]. Optional
104/// mutation counts and continuation values preserve backend observations.
105/// Ordinary writes may have uncertain outcomes after native failures;
106/// [`ReplacePartitionRequest`](crate::database::data::ReplacePartitionRequest) has its own stronger atomic contract.
107pub mod data {
108    pub use crate::core::{
109        ComparisonOp, CountRequest, DataRecord, DataRequest, DataResponse, DeleteRequest,
110        DenseVector, FilterExpr, InsertRequest, MutationResult, PageToken, Projection, RecordId,
111        RecordsPage, ReplacePartitionRequest, ScanRequest, UpdateAssignment, UpdateRequest,
112        WriteMode,
113    };
114}
115
116/// Portable retained search operations.
117///
118/// Build a [`QueryScope`](crate::database::query::QueryScope) and [`ScopedQuery`](crate::database::query::ScopedQuery) with vector or text options, then
119/// execute a [`QueryRequest`](crate::database::query::QueryRequest) through [`crate::DatabaseBackend::query`]. Read
120/// [`ScoredRecord::score_kind`](crate::database::query::ScoredRecord::score_kind) before interpreting scores and return page
121/// tokens unchanged to the same applicable operation.
122pub mod query {
123    pub use crate::core::{
124        DenseVector, DistanceMetric, NearestRequest, Projection, QueryRequest, QueryResponse,
125        QueryScope, ScopedQuery, ScoreKind, ScoredRecord, ScrollRequest, TextQueryOptions,
126        TextSearchRequest, VectorCoercionPolicy, VectorQueryOptions, VectorSearchParams,
127    };
128}
129
130/// Portable index lifecycle.
131///
132/// Execute [`IndexRequest`](crate::database::index::IndexRequest) through [`crate::DatabaseBackend::index`]. Creation
133/// and readiness observation are separate; unsupported kinds fail explicitly
134/// and optional metadata remains absent when it cannot be reported.
135pub mod index {
136    pub use crate::core::{
137        CreateIndexRequest, DistanceMetric, IndexInfo, IndexKind, IndexRequest, IndexResponse,
138        WaitForIndexRequest,
139    };
140}
141
142pub use crate::core::{CapabilitySet, StorageLocator};