use nodedb_types::DatabaseId;
use crate::control::security::identity::AuthenticatedIdentity;
use crate::control::state::SharedState;
use super::super::super::result::{DdlError, DdlResult};
use super::super::auth_support::require_tenant_admin;
fn err(sqlstate: &str, message: String) -> DdlError {
DdlError {
sqlstate: sqlstate.to_string(),
message,
}
}
pub fn alter_retention_policy(
state: &SharedState,
identity: &AuthenticatedIdentity,
database_id: DatabaseId,
name: &str,
action: &str,
set_key: Option<&str>,
set_value: Option<&str>,
) -> Result<Vec<DdlResult>, DdlError> {
require_tenant_admin(identity, "alter retention policies")?;
let tenant_id = identity.tenant_id.as_u64();
let mut def = state
.retention_policy_registry
.get(database_id.as_u64(), tenant_id, name)
.ok_or_else(|| err("42704", format!("retention policy '{name}' does not exist")))?;
match action {
"ENABLE" => def.enabled = true,
"DISABLE" => def.enabled = false,
"SET" => {
let key = set_key.unwrap_or("");
let val = set_value.unwrap_or("");
match key {
"AUTO_TIER" => {
def.auto_tier = val.eq_ignore_ascii_case("TRUE");
}
"EVAL_INTERVAL" => {
let ms = nodedb_types::kv_parsing::parse_interval_to_ms(val)
.map_err(|e| err("42601", format!("invalid interval: {e}")))?;
def.eval_interval_ms = ms;
}
_ => {
return Err(err(
"42601",
"ALTER RETENTION POLICY SET supports: AUTO_TIER, EVAL_INTERVAL".to_string(),
));
}
}
}
_ => {
return Err(err("42601", "expected ENABLE, DISABLE, or SET".to_string()));
}
}
let catalog = state.credentials.catalog();
catalog
.put_retention_policy(&def)
.map_err(|e| err("XX000", format!("catalog write: {e}")))?;
state.retention_policy_registry.register(def);
state.audit_record(
crate::control::security::audit::AuditEvent::AdminAction,
Some(identity.tenant_id),
&identity.username,
&format!("ALTER RETENTION POLICY {name}"),
);
Ok(vec![DdlResult::Status {
command: "ALTER RETENTION POLICY".to_string(),
rows_affected: None,
}])
}