use pgrx::PgBuiltInOids;
use pgrx::PgOid;
use pgrx::datum::DatumWithOid;
use pgrx::prelude::*;
use std::sync::Mutex;
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")
}
#[pg_extern]
const fn pg_tviews_hook_status() -> &'static str {
"Extension loaded - hook installation attempted in _PG_init"
}
#[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)? {
Spi::run_with_args(
&format!(
"SELECT {}.pg_tviews_refresh($1)",
crate::utils::ext_schema()
),
&[unsafe {
DatumWithOid::new(entity_name, PgOid::BuiltIn(PgBuiltInOids::TEXTOID).value())
}],
)?;
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);
}
#[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();
}
}