use std::pin::Pin;
use std::sync::Arc;
use anyhow::Result;
use arrow_array::RecordBatch;
use arrow_schema::Schema as ArrowSchema;
use async_trait::async_trait;
use futures::Stream;
use super::types::*;
pub type RecordBatchStream = Pin<Box<dyn Stream<Item = Result<RecordBatch>> + Send>>;
#[async_trait]
pub trait StorageBackend: Send + Sync + 'static {
async fn table_names(&self) -> Result<Vec<String>>;
async fn table_exists(&self, name: &str) -> Result<bool>;
async fn create_table(&self, name: &str, batches: Vec<RecordBatch>) -> Result<()>;
async fn create_empty_table(&self, name: &str, schema: Arc<ArrowSchema>) -> Result<()>;
async fn open_or_create_table(&self, name: &str, schema: Arc<ArrowSchema>) -> Result<()>;
async fn drop_table(&self, name: &str) -> Result<()>;
async fn scan(&self, request: ScanRequest) -> Result<Vec<RecordBatch>>;
async fn scan_stream(&self, request: ScanRequest) -> Result<RecordBatchStream>;
async fn get_table_schema(&self, name: &str) -> Result<Option<Arc<ArrowSchema>>>;
async fn count_rows(&self, table_name: &str, filter: Option<&str>) -> Result<usize>;
async fn write(
&self,
table_name: &str,
batches: Vec<RecordBatch>,
mode: WriteMode,
) -> Result<()>;
async fn delete_rows(&self, table_name: &str, filter: &str) -> Result<()>;
async fn replace_table_atomic(
&self,
name: &str,
batches: Vec<RecordBatch>,
schema: Arc<ArrowSchema>,
) -> Result<()>;
async fn get_table_version(&self, table_name: &str) -> Result<Option<u64>>;
async fn rollback_table(&self, table_name: &str, target_version: u64) -> Result<()>;
async fn optimize_table(&self, table_name: &str) -> Result<()>;
async fn recover_staging(&self, table_name: &str) -> Result<()>;
fn invalidate_cache(&self, _table_name: &str) {}
fn clear_cache(&self) {}
fn base_uri(&self) -> &str;
fn supports_vector_search(&self) -> bool {
false
}
fn supports_full_text_search(&self) -> bool {
false
}
fn supports_scalar_index(&self) -> bool {
false
}
async fn vector_search(
&self,
_table: &str,
_column: &str,
_query: &[f32],
_k: usize,
_metric: DistanceMetric,
_filter: FilterExpr,
) -> Result<Vec<RecordBatch>> {
anyhow::bail!("Vector search not supported by this backend")
}
async fn full_text_search(
&self,
_table: &str,
_column: &str,
_query: &str,
_k: usize,
_filter: FilterExpr,
) -> Result<Vec<RecordBatch>> {
anyhow::bail!("Full-text search not supported by this backend")
}
async fn create_vector_index(
&self,
_table: &str,
_column: &str,
_config: VectorIndexConfig,
) -> Result<()> {
anyhow::bail!("Vector indexing not supported by this backend")
}
async fn create_fts_index(&self, _table: &str, _column: &str) -> Result<()> {
anyhow::bail!("FTS indexing not supported by this backend")
}
async fn create_scalar_index(
&self,
_table: &str,
_column: &str,
_index_type: ScalarIndexType,
) -> Result<()> {
anyhow::bail!("Scalar indexing not supported by this backend")
}
async fn drop_index(&self, _table: &str, _index_name: &str) -> Result<()> {
anyhow::bail!("Index drop not supported by this backend")
}
async fn list_indexes(&self, _table: &str) -> Result<Vec<IndexInfo>> {
Ok(vec![])
}
}