use nodedb_types::protocol::NativeResponse;
use crate::control::server::shared::session::savepoint_ops::{self, SavepointError};
use super::DispatchCtx;
use super::transaction::NativeTxnDp;
fn savepoint_error_to_native(seq: u64, e: &SavepointError) -> NativeResponse {
match e {
SavepointError::NoActiveTransaction => NativeResponse::error(
seq,
"25P01",
"SAVEPOINT can only be used in transaction blocks",
),
SavepointError::NotFound { message } => {
NativeResponse::error(seq, "3B001", message.clone())
}
}
}
pub(crate) async fn handle_savepoint(
ctx: &DispatchCtx<'_>,
seq: u64,
sql_trimmed: &str,
) -> NativeResponse {
let sp_name = sql_trimmed.split_whitespace().nth(1).unwrap_or("sp");
let dp = NativeTxnDp { state: ctx.state };
match savepoint_ops::run_savepoint(ctx.sessions, ctx.peer_addr, ctx.tenant_id(), &dp, sp_name)
.await
{
Ok(()) => NativeResponse::status_row(seq, "SAVEPOINT"),
Err(e) => savepoint_error_to_native(seq, &e),
}
}
pub(crate) fn handle_release_savepoint(
ctx: &DispatchCtx<'_>,
seq: u64,
sql_trimmed: &str,
) -> NativeResponse {
let sp_name = sql_trimmed.split_whitespace().last().unwrap_or("sp");
match savepoint_ops::run_release_savepoint(ctx.sessions, ctx.peer_addr, sp_name) {
Ok(()) => NativeResponse::status_row(seq, "RELEASE"),
Err(e) => savepoint_error_to_native(seq, &e),
}
}
pub(crate) async fn handle_rollback_to_savepoint(
ctx: &DispatchCtx<'_>,
seq: u64,
sql_trimmed: &str,
) -> NativeResponse {
let sp_name = sql_trimmed.split_whitespace().last().unwrap_or("sp");
let dp = NativeTxnDp { state: ctx.state };
match savepoint_ops::run_rollback_to_savepoint(
ctx.sessions,
ctx.peer_addr,
ctx.tenant_id(),
&dp,
sp_name,
)
.await
{
Ok(()) => NativeResponse::status_row(seq, "ROLLBACK"),
Err(e) => savepoint_error_to_native(seq, &e),
}
}