use sqlx::Row as _;
use crate::orm::Db;
use crate::view_layer::ViewSpec;
use crate::Result;
const CREATE_TABLE_SQL: &str = "CREATE TABLE IF NOT EXISTS rustio_admin_view_specs (
model TEXT PRIMARY KEY,
spec_json TEXT NOT NULL,
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
)";
pub(crate) async fn ensure_table(db: &Db) -> Result<()> {
sqlx::query(CREATE_TABLE_SQL).execute(db.pool()).await?;
Ok(())
}
pub async fn load(db: &Db, model: &str) -> Result<Option<ViewSpec>> {
ensure_table(db).await?;
let row = sqlx::query("SELECT spec_json FROM rustio_admin_view_specs WHERE model = $1")
.bind(model)
.fetch_optional(db.pool())
.await?;
match row {
Some(r) => {
let json: String = r.try_get("spec_json")?;
let spec: ViewSpec = serde_json::from_str(&json)?;
Ok(Some(spec))
}
None => Ok(None),
}
}
pub async fn saved_models(db: &Db) -> Result<Vec<String>> {
ensure_table(db).await?;
let rows = sqlx::query("SELECT model FROM rustio_admin_view_specs ORDER BY model ASC")
.fetch_all(db.pool())
.await?;
Ok(rows
.iter()
.filter_map(|r| r.try_get::<String, _>("model").ok())
.collect())
}
pub async fn save(db: &Db, model: &str, spec: &ViewSpec) -> Result<()> {
ensure_table(db).await?;
let json = serde_json::to_string(spec)?;
sqlx::query(
"INSERT INTO rustio_admin_view_specs (model, spec_json, updated_at) \
VALUES ($1, $2, NOW()) \
ON CONFLICT (model) DO UPDATE SET spec_json = EXCLUDED.spec_json, updated_at = NOW()",
)
.bind(model)
.bind(json)
.execute(db.pool())
.await?;
Ok(())
}