use crate::error::TViewResult;
use pgrx::pg_sys;
fn update(table: pg_sys::Oid, sql: &str, names: &[String]) -> TViewResult<()> {
let _owner = crate::owner::AsOwner::of_extension()?;
crate::utils::spi::run(
&format!(
"UPDATE {} SET managed_index_names = {sql} \
WHERE table_oid = $1::pg_catalog.oid::pg_catalog.regclass",
crate::catalog::meta_table()
),
&[
crate::utils::spi::oid(table),
crate::utils::spi::text_array_of(names),
],
)
}
pub(crate) fn record(table: pg_sys::Oid, names: &[String]) -> TViewResult<()> {
update(
table,
"ARRAY(SELECT DISTINCT n FROM pg_catalog.unnest(\
pg_catalog.array_cat(COALESCE(managed_index_names, '{}'), $2)) n ORDER BY n)",
names,
)
}
pub(crate) fn forget(table: pg_sys::Oid, names: &[String]) -> TViewResult<()> {
if names.is_empty() {
return Ok(());
}
update(
table,
"ARRAY(SELECT n FROM pg_catalog.unnest(managed_index_names) n \
WHERE n <> ALL ($2) ORDER BY n)",
names,
)
}
pub(crate) fn rename(table: pg_sys::Oid, old: &str, new: &str) -> TViewResult<()> {
if recorded(table)?.iter().any(|n| n == old) {
forget(table, &[old.to_string()])?;
record(table, &[new.to_string()])?;
}
Ok(())
}
pub(crate) fn recorded(table: pg_sys::Oid) -> TViewResult<Vec<String>> {
crate::utils::spi::strings(
&format!(
"SELECT n FROM {} m, pg_catalog.unnest(m.managed_index_names) n \
WHERE m.table_oid = $1::pg_catalog.oid::pg_catalog.regclass ORDER BY n",
crate::catalog::meta_table()
),
&[crate::utils::spi::oid(table)],
)
}
pub(crate) fn unrecorded(table: pg_sys::Oid) -> TViewResult<bool> {
Ok(crate::utils::spi::one::<bool>(
&format!(
"SELECT managed_index_names IS NULL FROM {} \
WHERE table_oid = $1::pg_catalog.oid::pg_catalog.regclass",
crate::catalog::meta_table()
),
&[crate::utils::spi::oid(table)],
)?
.unwrap_or(false))
}
pub(crate) fn declared(entity: &str) -> TViewResult<serde_json::Value> {
let stored = crate::utils::spi::one::<pgrx::JsonB>(
&format!(
"SELECT declared_indexes FROM {} WHERE entity = $1",
crate::catalog::meta_table()
),
&[crate::utils::spi::text(entity)],
)?;
Ok(stored.map_or_else(|| serde_json::Value::Array(Vec::new()), |s| s.0))
}
pub(crate) fn declare(entity: &str, indexes: serde_json::Value) -> TViewResult<()> {
let _owner = crate::owner::AsOwner::of_extension()?;
crate::utils::spi::run(
&format!(
"UPDATE {} SET declared_indexes = $2 WHERE entity = $1",
crate::catalog::meta_table()
),
&[
crate::utils::spi::text(entity),
crate::utils::spi::jsonb(pgrx::JsonB(indexes)),
],
)
}
pub(crate) fn user_index_filter() -> String {
format!(
"i.indrelid = $1 \
AND NOT EXISTS (SELECT 1 FROM pg_catalog.pg_constraint k \
WHERE k.conindid = i.indexrelid) \
AND ic.relname <> ALL (SELECT pg_catalog.unnest(m.managed_index_names) \
FROM {} m WHERE m.table_oid = $1::pg_catalog.oid::pg_catalog.regclass)",
crate::catalog::meta_table()
)
}