use sqlx::{postgres::PgConnection, Pool, Postgres};
use tracing::instrument;
use crate::{
collection::ProjectInfo,
models, queries,
types::{DateTime, Json},
};
#[cfg(feature = "python")]
use crate::types::JsonPython;
#[cfg(feature = "c")]
use crate::languages::c::JsonC;
#[cfg(feature = "rust_bridge")]
use rust_bridge::{alias, alias_methods};
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub(crate) struct SplitterDatabaseData {
pub id: i64,
pub created_at: DateTime,
}
#[cfg_attr(feature = "rust_bridge", derive(alias))]
#[derive(Debug, Clone)]
pub struct Splitter {
pub(crate) name: String,
pub(crate) parameters: Json,
pub(crate) database_data: Option<SplitterDatabaseData>,
}
impl Default for Splitter {
fn default() -> Self {
Self::new(None, None)
}
}
#[cfg_attr(feature = "rust_bridge", alias_methods(new))]
impl Splitter {
pub fn new(name: Option<String>, parameters: Option<Json>) -> Self {
let name = name.unwrap_or("recursive_character".to_string());
let parameters = parameters.unwrap_or(Json(serde_json::json!({})));
Self {
name,
parameters,
database_data: None,
}
}
#[instrument(skip(self))]
pub(crate) async fn verify_in_database(
&mut self,
project_info: &ProjectInfo,
throw_if_exists: bool,
pool: &Pool<Postgres>,
) -> anyhow::Result<()> {
if self.database_data.is_none() {
let splitter: Option<models::Splitter> = sqlx::query_as(
"SELECT * FROM pgml.splitters WHERE project_id = $1 AND name = $2 and parameters = $3",
)
.bind(project_info.id)
.bind(&self.name)
.bind(&self.parameters)
.fetch_optional(pool)
.await?;
let splitter = if let Some(s) = splitter {
anyhow::ensure!(!throw_if_exists, "Splitter already exists in database");
s
} else {
sqlx::query_as(
"INSERT INTO pgml.splitters (project_id, name, parameters) VALUES ($1, $2, $3) RETURNING *",
)
.bind(project_info.id)
.bind(&self.name)
.bind(&self.parameters)
.fetch_one(pool)
.await?
};
self.database_data = Some(SplitterDatabaseData {
id: splitter.id,
created_at: splitter.created_at,
});
}
Ok(())
}
pub(crate) async fn create_splitters_table(conn: &mut PgConnection) -> anyhow::Result<()> {
sqlx::query(queries::CREATE_SPLITTERS_TABLE)
.execute(conn)
.await?;
Ok(())
}
}
impl From<models::Splitter> for Splitter {
fn from(splitter: models::Splitter) -> Self {
Self {
name: splitter.name,
parameters: splitter.parameters,
database_data: Some(SplitterDatabaseData {
id: splitter.id,
created_at: splitter.created_at,
}),
}
}
}