Postgres helpers the scan needs that are static inline or macros in
the headers, so bindgen does not carry them, and thin iterators over
List. Each mirrors the PG18 definition named in its comment.
5use std::ffi::c_void;
7use pgrx::{pg_guard, pg_sys};
ExecProcNode (executor.h).
Safety
node is an initialized plan state of the running executor.
TupIsNull (tuptable.h).
Safety
slot is NULL or a valid slot.
ExecClearTuple (tuptable.h).
Safety
slot is a valid slot.
slot_getallattrs (tuptable.h).
Safety
slot is a valid, non-empty slot.
ExecCopySlotMinimalTuple (tuptable.h): a copy in the current memory
context.
Safety
slot is a valid, non-empty slot.
57pub unsafe fn copy_minimal_tuple(slot: *mut pg_sys::TupleTableSlot) -> pg_sys::MinimalTuple { 58 let copy = unsafe { (*(*slot).tts_ops).copy_minimal_tuple.expect("slot ops copy") }; 59 // PG18 added `extra`, bytes reserved before the tuple; none here. 60 #[cfg(feature = "pg17")] 61 return unsafe { copy(slot) }; 62 #[cfg(not(feature = "pg17"))] 63 return unsafe { copy(slot, 0) }; 64}
ExecEvalExprSwitchContext (executor.h).
Safety
state was initialized for a plan node of the running executor, and
econtext is that node's expression context.
71pub unsafe fn eval_expr(state: *mut pg_sys::ExprState, econtext: *mut pg_sys::ExprContext) -> Option<pg_sys::Datum> { 72 unsafe { 73 let old = pg_sys::CurrentMemoryContext; 74 pg_sys::CurrentMemoryContext = (*econtext).ecxt_per_tuple_memory; 75 let mut isnull = false; 76 let datum = (*state).evalfunc.expect("an initialized ExprState has evalfunc")(state, econtext, &mut isnull); 77 pg_sys::CurrentMemoryContext = old; 78 (!isnull).then_some(datum) 79 } 80}
ResetExprContext (executor.h).
Safety
econtext is a live expression context.
InvokeFunctionExecuteHook (objectaccess.h).
Safety
Called inside a transaction.
IsA(node, tag) (nodes.h).
Safety
node is NULL or points to a Node.
list_length (pg_list.h).
Safety
list is NIL or a List.
The pointer elements of list (NIL is empty).
Safety
list is NIL or a pointer List whose elements are *mut T, and it is
not modified while the iterator lives.
The integer elements of an IntList (NIL is empty).
Safety
As [ptrs], for an IntList.
list with Ts appended.
Safety
list is NIL or a pointer List; the pointers stay valid as long as it.
Visits every node of an expression tree, depth first, as
expression_tree_walker does; visit returns false to skip a node's
children. visit must not raise an ERROR.
Safety
node is NULL or an expression tree.
153pub unsafe fn walk(node: *mut pg_sys::Node, visit: &mut dyn FnMut(*mut pg_sys::Node) -> bool) { 154 #[pg_guard] 155 unsafe extern "C-unwind" fn walker(node: *mut pg_sys::Node, context: *mut c_void) -> bool { 156 if node.is_null() { 157 return false; 158 } 159 // SAFETY: `context` is the `&mut dyn FnMut` passed below, alive 160 // for the whole walk. 161 let visit = unsafe { &mut *(context as *mut &mut dyn FnMut(*mut pg_sys::Node) -> bool) }; 162 if visit(node) { 163 unsafe { pg_sys::expression_tree_walker_impl(node, Some(walker), context) }; 164 } 165 false 166 } 167 let mut visit = visit; 168 unsafe { walker(node, (&raw mut visit).cast()) }; 169}
Rebuilds an expression tree, as expression_tree_mutator does:
replace returns a node to put in place of one (its children are not
visited), or None to copy it and visit its children. replace must
not raise an ERROR.
Safety
node is NULL or an expression tree.
178pub unsafe fn mutate( 179 node: *mut pg_sys::Node, 180 replace: &mut dyn FnMut(*mut pg_sys::Node) -> Option<*mut pg_sys::Node>, 181) -> *mut pg_sys::Node { 182 #[pg_guard] 183 unsafe extern "C-unwind" fn mutator(node: *mut pg_sys::Node, context: *mut c_void) -> *mut pg_sys::Node { 184 if node.is_null() { 185 return node; 186 } 187 // SAFETY: `context` is the `&mut dyn FnMut` passed below, alive 188 // for the whole walk. 189 let replace = unsafe { &mut *(context as *mut &mut dyn FnMut(*mut pg_sys::Node) -> Option<*mut pg_sys::Node>) }; 190 match replace(node) { 191 Some(new) => new, 192 None => unsafe { pg_sys::expression_tree_mutator_impl(node, Some(mutator), context) }, 193 } 194 } 195 let mut replace = replace; 196 unsafe { mutator(node, (&raw mut replace).cast()) } 197}