use pgwire::api::results::{Response, Tag};
use pgwire::error::PgWireResult;
use crate::control::maintenance::clone_materializer::{
CloneMaterializerHandle, force_materialize_blocking,
};
use crate::control::security::identity::AuthenticatedIdentity;
use crate::control::state::SharedState;
use super::super::super::types::{require_database_owner_or_higher, sqlstate_error};
pub fn handle_alter_database_materialize(
state: &SharedState,
identity: &AuthenticatedIdentity,
name: &str,
) -> PgWireResult<Vec<Response>> {
let catalog = state
.credentials
.catalog()
.as_ref()
.ok_or_else(|| sqlstate_error("XX000", "system catalog unavailable"))?;
let db_id = catalog
.get_database_id_by_name(name)
.map_err(|e| sqlstate_error("XX000", &format!("catalog lookup failed: {e}")))?
.ok_or_else(|| sqlstate_error("3D000", &format!("database '{name}' does not exist")))?;
require_database_owner_or_higher(
state,
identity,
db_id,
&format!("ALTER DATABASE {name} MATERIALIZE"),
)?;
let handle = CloneMaterializerHandle::new(db_id);
force_materialize_blocking(db_id, state, catalog, Some(&handle)).map_err(|e| match e {
crate::Error::BadRequest { detail } => sqlstate_error("0A000", &detail),
other => sqlstate_error(
"XX000",
&format!("clone materialization of '{name}' failed: {other}"),
),
})?;
state.audit_record_with_db(
crate::control::security::audit::AuditEvent::DatabaseMaterialized,
None,
Some(db_id),
&identity.username,
&format!("ALTER DATABASE {name} MATERIALIZE"),
);
Ok(vec![Response::Execution(Tag::new("ALTER DATABASE"))])
}