use systemprompt_extension::LoaderError;
use crate::lifecycle::migrations::{BaselineStamp, RECORD_MIGRATION_SQL};
use crate::services::DatabaseProvider;
pub(super) async fn execute_phase(
db: &dyn DatabaseProvider,
statements: &[String],
stamp: &[BaselineStamp],
extension_id: &str,
) -> Result<(), LoaderError> {
if statements.is_empty() && stamp.is_empty() {
return Ok(());
}
let mut tx =
db.begin_transaction()
.await
.map_err(|e| LoaderError::SchemaInstallationFailed {
extension: extension_id.to_owned(),
message: format!("Failed to begin transaction: {e}"),
})?;
let total = statements.len();
for (idx, statement) in statements.iter().enumerate() {
let sql_str: &str = statement.as_str();
if let Err(e) = tx.execute(&sql_str, &[]).await {
let rollback_note = match tx.rollback().await {
Ok(()) => String::new(),
Err(rb) => format!(" (rollback also failed: {rb})"),
};
return Err(LoaderError::SchemaInstallationFailed {
extension: extension_id.to_owned(),
message: format!(
"Statement {n}/{total} failed: {e}{rollback_note}\nSQL:\n{statement}",
n = idx + 1,
),
});
}
}
for row in stamp {
let params: [&dyn systemprompt_identifiers::ToDbValue; 5] = [
&row.id,
&extension_id,
&row.version,
&row.name,
&row.checksum,
];
if let Err(e) = tx.execute(&RECORD_MIGRATION_SQL, ¶ms).await {
let rollback_note = match tx.rollback().await {
Ok(()) => String::new(),
Err(rb) => format!(" (rollback also failed: {rb})"),
};
return Err(LoaderError::SchemaInstallationFailed {
extension: extension_id.to_owned(),
message: format!(
"Failed to stamp migration {} ({}) as applied: {e}{rollback_note}",
row.version, row.name
),
});
}
}
tx.commit()
.await
.map_err(|e| LoaderError::SchemaInstallationFailed {
extension: extension_id.to_owned(),
message: format!("Failed to commit transaction: {e}"),
})?;
Ok(())
}