Skip to main content

Database

Struct Database 

Source
pub struct Database { /* private fields */ }
Expand description

Main database handle

This is the primary interface for interacting with a CQLite database. It coordinates between the storage engine, schema manager, and query engine.

Implementations§

Source§

impl Database

Source

pub async fn open(path: &Path, config: Config) -> Result<Self>

Open a database at the given path with the specified configuration

§Arguments
  • path - The directory path where the database files will be stored
  • config - Database configuration options
§Errors

Returns an error if:

  • The path cannot be created or accessed
  • Database files are corrupted
  • Configuration is invalid
§Examples
use cqlite_core::{Database, Config};
use std::path::{Path, PathBuf};

let config = Config::default();
let db = Database::open(Path::new("./data"), config).await?;
Source

pub async fn open_with_discovered_sstables( storage_path: &Path, discovered_table_dirs: Vec<PathBuf>, config: Config, ) -> Result<Self>

Open a database with pre-discovered SSTable table directories

This method is used in the ingestion flow where SSTable discovery has been performed externally (e.g., via DiscoveryService) and the database should be initialized with specific SSTable files rather than scanning the storage directory.

§Use Case

This method is designed for the one-shot ingestion workflow:

  1. DiscoveryService::discover() scans external Cassandra data directories
  2. SchemaManager parses schema from discovered files
  3. Database::open_with_discovered_sstables() creates a queryable database instance
§Arguments
  • storage_path - The directory path for database runtime files (WAL, manifest, memtable)
  • discovered_table_dirs - Vector of table directory paths from DiscoveryService (e.g., /var/lib/cassandra/data/keyspace1/table1-abc123)
  • config - Database configuration options
§Errors

Returns an error if:

  • The storage path cannot be created or accessed
  • Any discovered table directory cannot be read
  • Configuration is invalid
  • Storage engine or query engine initialization fails
§Feature Gates

This method is only available when the state_machine feature is enabled (default in M2+).

§Examples
use cqlite_core::{Database, Config};
use std::path::{Path, PathBuf};

let config = Config::default();
let storage_path = Path::new("./runtime");
let discovered_dirs = vec![
    PathBuf::from("/var/lib/cassandra/data/keyspace1/table1-abc123"),
    PathBuf::from("/var/lib/cassandra/data/keyspace1/table2-def456"),
];

let db = Database::open_with_discovered_sstables(
    storage_path,
    discovered_dirs,
    config
).await?;
Source

pub async fn refresh(&self) -> Result<RefreshReport>

Re-scan the data directory and atomically apply added/removed SSTable generations to this handle’s reader set (issue #1749).

§Freshness contract

A Database is a snapshot at open: it discovers the SSTable generations once and never re-scans on its own. A Cassandra flush/compaction (or a CQLite --flush) may add or remove generations underneath a warm handle at any time; those changes become visible only after an explicit refresh(). Re-runs the same TOC/filename-based discovery open used — no content sniffing, no heuristics.

  • Newly present generations become queryable; removed generations stop being queried; unchanged generations keep their warm parsed Index/Statistics/bloom state (not rebuilt).
  • In-flight queries are never affected: a scan already running holds its own Arc reader clones and completes against the pre-refresh set. A query issued after refresh() returns sees the post-refresh set.
  • Atomic and fail-closed: if any newly discovered generation fails to open (e.g. a corrupt Statistics.db, issue #1626), refresh() returns the typed error and leaves the previously held reader set fully unchanged — no partial view.

Returns a RefreshReport describing what this call applied. Explicit refresh only: there is no filesystem watching or per-query staleness check.

Source

pub async fn execute(&self, sql: &str) -> Result<QueryResult>

Execute a SQL query and return the result

§Arguments
  • sql - The SQL query string to execute
§Errors

Returns an error if:

  • SQL syntax is invalid
  • Referenced tables/columns don’t exist
  • Query execution fails
§Examples
let result = db.execute("SELECT * FROM users WHERE id = 1").await?;
Source

pub async fn execute_streaming( &self, sql: &str, config: StreamingConfig, ) -> Result<QueryResultIterator>

Execute a SQL query with streaming results (Issue #280)

Returns a QueryResultIterator that yields rows incrementally via a bounded channel, enabling memory-efficient processing of large result sets.

This is the recommended method for exporting large tables, as it avoids materializing all rows in memory at once.

§Arguments
  • sql - The SQL query to execute (must be a SELECT statement)
  • config - Streaming configuration (buffer size, chunk hints)
§Errors

Returns an error if:

  • Query is not a SELECT statement
  • SQL syntax is invalid
  • Query execution fails
§Examples
let config = StreamingConfig::default();
let mut iter = db.execute_streaming(
    "SELECT * FROM large_table",
    config
).await?;

while let Some(row_result) = iter.next_async().await {
    let row = row_result?;
    // Process row incrementally
}
Source

pub async fn execute_with_params( &self, sql: &str, params: &[Value], ) -> Result<QueryResult>

Execute a SELECT with positional ? parameters (Issue #961).

The params are bound, in source order, into the statement’s ? placeholders before planning, so they participate in partition-key classification and encoding. A WHERE pk = ? therefore engages the same partition-targeted fast path as the equivalent literal query.

§Arguments
  • sql - A SELECT statement that may contain positional ? placeholders
  • params - Values bound positionally to the ? placeholders
§Errors

Returns an error if the SQL is not a SELECT, the parameter count does not match the number of ? placeholders, or execution fails.

Source

pub async fn prepare(&self, sql: &str) -> Result<Arc<PreparedQuery>>

Prepare a SQL statement for repeated execution

§Arguments
  • sql - The SQL statement to prepare
§Errors

Returns an error if SQL syntax is invalid or references non-existent objects

Source

pub async fn explain(&self, sql: &str) -> Result<ExplainResult>

Explain a SQL query without executing it

§Arguments
  • sql - The SQL query to explain
§Errors

Returns an error if SQL syntax is invalid

Source

pub async fn has_schema_for_table(&self, table: &str) -> bool

Check if schema is available for a table

This is a fast boolean check useful for pre-flight validation. For detailed diagnostic information, use schema_status().

§Examples
let db = Database::open(std::path::Path::new("./data"), Config::default()).await?;

if !db.has_schema_for_table("users").await {
    eprintln!("Warning: No schema found for 'users' table");
}
Source

pub async fn schema_status(&self, table: &str) -> SchemaStatus

Get detailed schema status for debugging

Returns diagnostic information about schema availability including reasons for missing schemas or extraction failures.

§Examples
let db = Database::open(std::path::Path::new("./data"), Config::default()).await?;

match db.schema_status("users").await {
    SchemaStatus::Available { .. } => println!("Schema ready"),
    SchemaStatus::ExtractionFailed { cause, suggestion, .. } => {
        eprintln!("Schema extraction failed: {}", cause);
        eprintln!("Suggestion: {}", suggestion);
    }
    _ => {}
}
Source

pub async fn stats(&self) -> Result<DatabaseStats>

Get database statistics

Source

pub async fn shutdown(&self) -> Result<()>

Shutdown the database storage engine without consuming self.

This is useful for language bindings where the Database is wrapped in an Arc and cannot be consumed. The shutdown operation is idempotent.

For consuming close that also drops the Database, use close().

Source

pub async fn close(self) -> Result<()>

Close the database and release all resources

This method ensures all pending operations are completed and all resources are properly cleaned up.

§Durability contract

Embedders MUST call close().await for a graceful shutdown. Drop is NOT a flush — Tokio has no async drop, so dropping a handle cannot await a flush and any un-flushed writer state is left to recovery (WAL replay) rather than being persisted here. For the write path this maps onto storage::write_engine::WriteEngine::close, which is the actual memtable-to-SSTable durability boundary (issue #1693).

Source

pub fn config(&self) -> &Config

Get the database configuration

Trait Implementations§

Source§

impl Clone for Database

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Database

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more