use pgrx::prelude::*;
use std::sync::Mutex;
pub const JSONB_DELTA_MISSING: &str = "jsonb_delta_missing";
static JSONB_DELTA_SCHEMA: Mutex<(bool, Option<String>)> = Mutex::new((false, None));
#[pg_extern]
#[allow(clippy::missing_const_for_fn)] fn pg_tviews_version() -> &'static str {
env!("CARGO_PKG_VERSION")
}
#[must_use]
pub fn check_jsonb_delta_available() -> bool {
jsonb_delta_schema().is_some()
}
pub fn jsonb_delta_schema() -> Option<String> {
let mut cache = JSONB_DELTA_SCHEMA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
if cache.0 {
return cache.1.clone();
}
let schema = Spi::connect(|client| {
client
.select(
"SELECT pg_catalog.quote_ident(n.nspname) \
FROM pg_catalog.pg_extension e \
JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace \
WHERE e.extname = 'jsonb_delta'",
None,
&[],
)?
.first()
.get_one::<String>()
})
.ok()
.flatten();
*cache = (true, schema.clone());
schema
}
#[pg_extern]
pub fn pg_tviews_recover_after_crash(entity_name: &str) -> crate::TViewResult<bool> {
crate::revision::check();
if detect_post_crash_truncation(entity_name)? {
crate::admin::rebuild_one(entity_name)?;
Ok(true)
} else {
Ok(false)
}
}
pub fn detect_post_crash_truncation(entity_name: &str) -> crate::TViewResult<bool> {
match crate::replication::TviewRelation::load(Some(entity_name))?.first() {
Some(rel) => rel.needs_rebuild(),
None => Ok(false), }
}
#[pg_extern]
fn pg_tviews_check_jsonb_delta() -> bool {
check_jsonb_delta_available()
}
pub fn invalidate_jsonb_delta_cache() {
*JSONB_DELTA_SCHEMA
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) = (false, None);
crate::utils::forget_logged(JSONB_DELTA_MISSING);
}
#[pg_guard]
pub extern "C-unwind" fn _PG_init() {
crate::config::register_gucs();
crate::queue::cache::register_relcache_callback();
crate::rebuild_worker::register();
unsafe {
crate::hooks::ensure_hook_installed();
}
unsafe {
crate::queue::xact::register_xact_callback();
crate::queue::xact::register_subxact_callback();
}
}