use pgrx::guc::{GucContext, GucFlags, GucRegistry, GucSetting};
pub const MAX_DEPENDENCY_DEPTH: usize = 10;
pub const DEBUG_DEPENDENCIES: bool = false;
static MAX_PROPAGATION_DEPTH_GUC: GucSetting<i32> = GucSetting::<i32>::new(100);
static GRAPH_CACHE_ENABLED_GUC: GucSetting<bool> = GucSetting::<bool>::new(true);
static TABLE_CACHE_ENABLED_GUC: GucSetting<bool> = GucSetting::<bool>::new(true);
static METRICS_ENABLED_GUC: GucSetting<bool> = GucSetting::<bool>::new(false);
static LOG_LEVEL_GUC: GucSetting<Option<std::ffi::CString>> =
GucSetting::<Option<std::ffi::CString>>::new(Some(c"info"));
static UNION_DUPLICATE_POLICY_GUC: GucSetting<Option<std::ffi::CString>> =
GucSetting::<Option<std::ffi::CString>>::new(Some(c"error"));
static MAX_QUEUE_SIZE_GUC: GucSetting<i32> = GucSetting::<i32>::new(10_000);
static AUDIT_ENABLED_GUC: GucSetting<bool> = GucSetting::<bool>::new(false);
static UNLOGGED_BY_DEFAULT_GUC: GucSetting<bool> = GucSetting::<bool>::new(true);
pub fn register_gucs() {
GucRegistry::define_int_guc(
c"pg_tviews.max_propagation_depth",
c"Maximum cascade propagation iterations before aborting.",
c"Prevents infinite loops in circular dependency chains.",
&MAX_PROPAGATION_DEPTH_GUC,
1, 10_000, GucContext::Userset,
GucFlags::default(),
);
GucRegistry::define_bool_guc(
c"pg_tviews.graph_cache_enabled",
c"Enable in-memory caching of entity dependency graphs.",
c"When false, graphs are loaded from pg_tview_meta on every refresh.",
&GRAPH_CACHE_ENABLED_GUC,
GucContext::Userset,
GucFlags::default(),
);
GucRegistry::define_bool_guc(
c"pg_tviews.table_cache_enabled",
c"Enable in-memory caching of table OID to entity name mappings.",
c"When false, entity lookups query pg_tview_meta on every trigger.",
&TABLE_CACHE_ENABLED_GUC,
GucContext::Userset,
GucFlags::default(),
);
GucRegistry::define_bool_guc(
c"pg_tviews.metrics_enabled",
c"Enable collection of refresh metrics.",
c"When true, per-transaction refresh statistics are tracked.",
&METRICS_ENABLED_GUC,
GucContext::Userset,
GucFlags::default(),
);
GucRegistry::define_string_guc(
c"pg_tviews.log_level",
c"Logging verbosity for pg_tviews operations.",
c"Allowed values: debug, info, warning, error.",
&LOG_LEVEL_GUC,
GucContext::Userset,
GucFlags::default(),
);
GucRegistry::define_string_guc(
c"pg_tviews.union_duplicate_policy",
c"Policy when a UNION ALL backing view returns multiple rows for the same key.",
c"Allowed values: 'first' (silently take first row), 'error' (abort transaction).",
&UNION_DUPLICATE_POLICY_GUC,
GucContext::Userset,
GucFlags::default(),
);
GucRegistry::define_int_guc(
c"pg_tviews.max_queue_size",
c"Maximum number of refresh items allowed in the transaction queue.",
c"When exceeded, new refresh enqueues raise an error to prevent unbounded queue growth.",
&MAX_QUEUE_SIZE_GUC,
1, 1_000_000, GucContext::Userset,
GucFlags::default(),
);
GucRegistry::define_bool_guc(
c"pg_tviews.audit_enabled",
c"Enable audit logging of TVIEW operations to pg_tview_audit_log.",
c"When false, refresh/create/drop operations are not logged.",
&AUDIT_ENABLED_GUC,
GucContext::Userset,
GucFlags::default(),
);
GucRegistry::define_bool_guc(
c"pg_tviews.unlogged_by_default",
c"Create TVIEW tables as UNLOGGED by default.",
c"When true, new TVIEWs are created as UNLOGGED tables for better write performance.",
&UNLOGGED_BY_DEFAULT_GUC,
GucContext::Userset,
GucFlags::default(),
);
}
#[must_use]
pub fn max_propagation_depth() -> usize {
MAX_PROPAGATION_DEPTH_GUC.get().unsigned_abs() as usize
}
#[must_use]
pub fn graph_cache_enabled() -> bool {
GRAPH_CACHE_ENABLED_GUC.get()
}
#[must_use]
pub fn table_cache_enabled() -> bool {
TABLE_CACHE_ENABLED_GUC.get()
}
#[must_use]
pub fn log_level() -> String {
LOG_LEVEL_GUC.get().map_or_else(
|| "info".to_owned(),
|cstr| cstr.to_str().unwrap_or("info").to_owned(),
)
}
#[must_use]
pub fn metrics_enabled() -> bool {
METRICS_ENABLED_GUC.get()
}
#[must_use]
pub fn union_duplicate_policy() -> String {
UNION_DUPLICATE_POLICY_GUC.get().map_or_else(
|| "error".to_owned(),
|cstr| cstr.to_str().unwrap_or("error").to_owned(),
)
}
#[must_use]
pub fn max_queue_size() -> usize {
MAX_QUEUE_SIZE_GUC.get().unsigned_abs() as usize
}
#[must_use]
pub fn audit_enabled() -> bool {
AUDIT_ENABLED_GUC.get()
}
#[must_use]
pub fn unlogged_by_default() -> bool {
UNLOGGED_BY_DEFAULT_GUC.get()
}