Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions pgrx-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,50 @@ mod framework;
pub use framework::*;
#[cfg(feature = "proptest")]
pub mod proptest;

// ── Test stubs ──────────────────────────────────────────────────────────────
// When a test binary links pgrx-pg-sys, all the extern "C" statics declared in
// the generated bindings become undefined symbols. Normally --gc-sections
// prunes unreachable references, but #[typetag::serde] / inventory::submit!
// ctors run before main() and pull pg_sys symbols into the live set.
//
// Because pgrx-tests is a dev-dependency, it is linked into test binaries but
// NOT into the extension .so. These #[unsafe(no_mangle)] statics satisfy the linker
// without ever shadowing the real PostgreSQL symbols at runtime.
// ─────────────────────────────────────────────────────────────────────────────
mod stubs {
use pgrx::pg_sys;

#[unsafe(no_mangle)]
pub static mut CurrentMemoryContext: pg_sys::MemoryContext = std::ptr::null_mut();

#[unsafe(no_mangle)]
pub static mut error_context_stack: *mut pg_sys::ErrorContextCallback = std::ptr::null_mut();

#[unsafe(no_mangle)]
pub static mut PG_exception_stack: *mut pg_sys::sigjmp_buf = std::ptr::null_mut();

#[unsafe(no_mangle)]
pub static mut emit_log_hook: pg_sys::emit_log_hook_type = None;

#[unsafe(no_mangle)]
pub static mut Log_error_verbosity: std::ffi::c_int = 0;

#[unsafe(no_mangle)]
pub static mut Log_line_prefix: *mut std::ffi::c_char = std::ptr::null_mut();

#[unsafe(no_mangle)]
pub static mut Log_destination: std::ffi::c_int = 0;

#[unsafe(no_mangle)]
pub static mut Log_destination_string: *mut std::ffi::c_char = std::ptr::null_mut();

#[unsafe(no_mangle)]
pub static mut syslog_sequence_numbers: bool = false;

#[unsafe(no_mangle)]
pub static mut syslog_split_messages: bool = false;

#[unsafe(no_mangle)]
pub static mut BufferBlocks: *mut std::ffi::c_void = std::ptr::null_mut();
}
43 changes: 43 additions & 0 deletions pgrx/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,49 @@ macro_rules! pg_magic_func {
// return the magic
&MY_MAGIC.0
}

// ── Test stubs ──
// When the test binary links, all extern "C" statics from
// pgrx-pg-sys become undefined symbols. #[typetag::serde]
// ctors pull them into the live set, defeating --gc-sections.
// These stubs compile ON THE EXTENSION SIDE where #[cfg(test)]
// actually fires, and provide #[unsafe(no_mangle)] definitions that
// satisfy the linker without shadowing PG's real symbols in the .so.
#[cfg(test)]
mod __pgrx_test_stubs {
#[unsafe(no_mangle)]
pub static mut CurrentMemoryContext: $crate::pg_sys::MemoryContext = std::ptr::null_mut();

#[unsafe(no_mangle)]
pub static mut error_context_stack: *mut $crate::pg_sys::ErrorContextCallback = std::ptr::null_mut();

#[unsafe(no_mangle)]
pub static mut PG_exception_stack: *mut $crate::pg_sys::sigjmp_buf = std::ptr::null_mut();

#[unsafe(no_mangle)]
pub static mut emit_log_hook: $crate::pg_sys::emit_log_hook_type = None;

#[unsafe(no_mangle)]
pub static mut Log_error_verbosity: std::ffi::c_int = 0;

#[unsafe(no_mangle)]
pub static mut Log_line_prefix: *mut std::ffi::c_char = std::ptr::null_mut();

#[unsafe(no_mangle)]
pub static mut Log_destination: std::ffi::c_int = 0;

#[unsafe(no_mangle)]
pub static mut Log_destination_string: *mut std::ffi::c_char = std::ptr::null_mut();

#[unsafe(no_mangle)]
pub static mut syslog_sequence_numbers: bool = false;

#[unsafe(no_mangle)]
pub static mut syslog_split_messages: bool = false;

#[unsafe(no_mangle)]
pub static mut BufferBlocks: *mut std::ffi::c_void = std::ptr::null_mut();
}
};
}

Expand Down