use std::future::Future;
#[derive(Debug, Clone)]
pub struct ColSpec {
pub name: &'static str,
pub type_ddl: String,
pub nullable: bool,
pub default: Option<&'static str>,
pub is_primary_key: bool,
}
pub trait BackendDialect {
const NAME: &'static str;
const SUPPORTS_UPSERT: bool;
fn quote_ident(&self, name: &str) -> String;
fn fq_table(&self, db: &str, table: &str) -> String;
fn vector_type_ddl(&self, dim: usize) -> String;
fn json_type_ddl(&self) -> String;
fn tags_array_type_ddl(&self) -> String;
fn text_pk_type_ddl(&self) -> String;
fn timestamp_now_default_ddl(&self) -> String;
fn vector_literal(&self, arr: &[f32]) -> String;
fn json_literal(&self, obj: &serde_json::Value) -> String;
fn json_path_sql(&self, col_expr: &str, dotted_path: &str) -> String;
fn upsert_clause(&self, key_cols: &[&str], update_cols: &[&str]) -> String;
fn create_database_sql(&self, name: &str) -> String;
fn add_column_if_not_exists_sql(&self, fq: &str, col: &str, type_ddl: &str) -> String;
fn drop_table_sql(&self, fq: &str) -> String;
fn emit_chunks_table_ddl(
&self,
fq: &str,
cols: &[ColSpec],
hnsw: bool,
dim: usize,
engine: Option<&str>,
vector_metric: Option<&str>,
) -> Vec<String>;
}
pub trait BackendConn {
type Db: sqlx::Database;
fn connect(&self) -> impl Future<Output = anyhow::Result<()>> + Send;
fn acquire_create_lock(
&self,
tx: &mut sqlx::Transaction<'_, Self::Db>,
key: &str,
) -> impl Future<Output = anyhow::Result<()>> + Send;
fn table_exists(
&self,
tx: &mut sqlx::Transaction<'_, Self::Db>,
db: &str,
table: &str,
) -> impl Future<Output = anyhow::Result<bool>> + Send;
fn embedding_dim(
&self,
tx: &mut sqlx::Transaction<'_, Self::Db>,
db: &str,
table: &str,
) -> impl Future<Output = anyhow::Result<Option<usize>>> + Send;
}
pub trait Backend: BackendDialect + BackendConn {}
impl<T: BackendDialect + BackendConn> Backend for T {}