use async_trait::async_trait;
use serde_json::Value;
use std::fmt::{Debug, Formatter, Result as StdResult};
use std::time::Instant;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BackendType {
Native,
Supabase,
Postgrest,
Scylla,
Neon,
PostgreSQL,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum QueryLanguage {
Sql,
Cql,
Postgrest,
}
#[derive(Debug, Clone)]
pub struct TranslatedQuery {
pub sql: String,
pub language: QueryLanguage,
pub params: Vec<Value>,
pub table: Option<String>,
}
impl TranslatedQuery {
pub fn new(
sql: impl Into<String>,
language: QueryLanguage,
params: Vec<Value>,
table: Option<String>,
) -> Self {
Self {
sql: sql.into(),
language,
params,
table,
}
}
}
#[derive(Clone)]
pub struct QueryResult {
pub rows: Vec<Value>,
pub columns: Vec<String>,
}
impl Debug for QueryResult {
fn fmt(&self, f: &mut Formatter<'_>) -> StdResult {
f.debug_struct("QueryResult")
.field("rows", &self.rows)
.field("columns", &self.columns)
.finish()
}
}
impl QueryResult {
pub fn new(rows: Vec<Value>, columns: Vec<String>) -> Self {
Self { rows, columns }
}
}
pub enum HealthStatus {
Healthy,
Offline(Instant),
}
pub type BackendResult<T> = Result<T, BackendError>;
#[derive(thiserror::Error, Debug)]
pub enum BackendError {
#[error("backend error: {0}")]
Generic(String),
}
#[async_trait]
pub trait DatabaseBackend: Send + Sync {
async fn execute_query(&self, query: TranslatedQuery) -> BackendResult<QueryResult>;
async fn health_check(&self) -> BackendResult<HealthStatus>;
fn backend_type(&self) -> BackendType;
fn supports_sql(&self) -> bool;
fn supports_cql(&self) -> bool;
fn as_any(&self) -> &dyn std::any::Any;
}