use super::{TViewError, drop_tview, pg_sys, resolve_relation_oid};
pub(super) unsafe fn handle_drop_table(
drop_stmt: *mut pg_sys::DropStmt,
_query_string: *const ::std::os::raw::c_char,
) -> Result<bool, TViewError> {
unsafe {
if drop_stmt.is_null() {
return Ok(false);
}
let drop_ref = &*drop_stmt;
if drop_ref.removeType != pg_sys::ObjectType::OBJECT_TABLE {
return Ok(false);
}
let objects = drop_ref.objects;
if objects.is_null() {
return Ok(false);
}
let if_exists = drop_ref.missing_ok;
let cascade = drop_ref.behavior == pg_sys::DropBehavior::DROP_CASCADE;
let num_tables = pg_sys::list_length(objects);
let mut tv_entries: Vec<(i32, String)> = Vec::new(); let mut has_non_tv = false;
for i in 0..num_tables {
let name_list = pg_sys::list_nth(objects, i).cast::<pg_sys::List>();
if name_list.is_null() || pg_sys::list_length(name_list) == 0 {
has_non_tv = true;
continue;
}
let rv = pg_sys::makeRangeVarFromNameList(name_list);
let relid = resolve_relation_oid(rv);
if relid == pg_sys::InvalidOid {
has_non_tv = true;
continue;
}
match crate::catalog::TviewMeta::entity_of_table(relid)? {
Some(entity) => tv_entries.push((i, format!("tv_{entity}"))),
None => has_non_tv = true,
}
}
if tv_entries.is_empty() {
return Ok(false);
}
for (_, name) in &tv_entries {
drop_tview(name, if_exists, cascade)?;
}
if has_non_tv {
for (idx, _) in tv_entries.iter().rev() {
pg_sys::list_delete_nth_cell(objects, *idx);
}
return Ok(false);
}
Ok(true)
} }