1use crate as pg_sys;
2use crate::BLCKSZ;
3use core::mem::offset_of;
4use core::str::FromStr;
5
6pub const InvalidOid: crate::Oid = crate::Oid::INVALID;
8pub const InvalidOffsetNumber: super::OffsetNumber = 0;
9pub const FirstOffsetNumber: super::OffsetNumber = 1;
10pub const MaxOffsetNumber: super::OffsetNumber =
11 (super::BLCKSZ as usize / std::mem::size_of::<super::ItemIdData>()) as super::OffsetNumber;
12pub const InvalidBlockNumber: u32 = 0xFFFF_FFFF as crate::BlockNumber;
13pub const VARHDRSZ: usize = std::mem::size_of::<super::int32>();
14pub const InvalidCommandId: super::CommandId = (!(0 as super::CommandId)) as super::CommandId;
15pub const FirstCommandId: super::CommandId = 0 as super::CommandId;
16pub const InvalidTransactionId: crate::TransactionId = crate::TransactionId::INVALID;
17pub const BootstrapTransactionId: crate::TransactionId = crate::TransactionId::BOOTSTRAP;
18pub const FrozenTransactionId: crate::TransactionId = crate::TransactionId::FROZEN;
19pub const FirstNormalTransactionId: crate::TransactionId = crate::TransactionId::FIRST_NORMAL;
20pub const MaxTransactionId: crate::TransactionId = crate::TransactionId::MAX;
21
22#[inline(always)]
28pub unsafe fn GETSTRUCT(tuple: crate::HeapTuple) -> *mut std::os::raw::c_char {
29 (*tuple).t_data.cast::<std::os::raw::c_char>().add((*(*tuple).t_data).t_hoff as _)
34}
35
36#[allow(non_snake_case)]
42#[inline(always)]
43pub const unsafe fn TYPEALIGN(alignval: usize, len: usize) -> usize {
44 ((len) + ((alignval) - 1)) & !((alignval) - 1)
47}
48
49#[allow(non_snake_case)]
50#[inline(always)]
51pub const unsafe fn MAXALIGN(len: usize) -> usize {
52 TYPEALIGN(pg_sys::MAXIMUM_ALIGNOF as _, len)
54}
55
56#[allow(non_snake_case)]
77pub unsafe fn GetMemoryChunkContext(pointer: *mut std::os::raw::c_void) -> pg_sys::MemoryContext {
78 #[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
79 {
80 assert!(!pointer.is_null());
88 assert_eq!(pointer, MAXALIGN(pointer as usize) as *mut ::std::os::raw::c_void);
89
90 let context = unsafe {
95 *(pointer
98 .cast::<::std::os::raw::c_char>()
99 .sub(std::mem::size_of::<*mut ::std::os::raw::c_void>())
100 .cast())
101 };
102
103 assert!(MemoryContextIsValid(context));
104
105 context
106 }
107 #[cfg(any(feature = "pg16", feature = "pg17", feature = "pg18", feature = "pg19"))]
108 {
109 #[pgrx_macros::pg_guard]
110 unsafe extern "C-unwind" {
111 #[link_name = "GetMemoryChunkContext"]
112 pub fn extern_fn(pointer: *mut std::os::raw::c_void) -> pg_sys::MemoryContext;
113 }
114 extern_fn(pointer)
115 }
116}
117
118#[allow(non_snake_case)]
129#[inline(always)]
130pub unsafe fn MemoryContextIsValid(context: crate::MemoryContext) -> bool {
131 !context.is_null()
138 && unsafe {
139 let tag = (*context.cast::<crate::Node>()).type_;
142 use crate::NodeTag::*;
143 matches!(tag, T_AllocSetContext | T_SlabContext | T_GenerationContext)
144 }
145}
146
147pub const VARHDRSZ_EXTERNAL: usize = offset_of!(super::varattrib_1b_e, va_data);
148pub const VARHDRSZ_SHORT: usize = offset_of!(super::varattrib_1b, va_data);
149
150#[inline]
151pub fn get_pg_major_version_string() -> &'static str {
152 super::PG_MAJORVERSION.to_str().unwrap()
153}
154
155#[inline]
156pub fn get_pg_major_version_num() -> u16 {
157 u16::from_str(super::get_pg_major_version_string()).unwrap()
158}
159
160#[cfg(any(not(target_env = "msvc"), feature = "pg17", feature = "pg18", feature = "pg19"))]
161#[inline]
162pub fn get_pg_version_string() -> &'static str {
163 super::PG_VERSION_STR.to_str().unwrap()
164}
165
166#[cfg(all(
167 target_env = "msvc",
168 any(feature = "pg13", feature = "pg14", feature = "pg15", feature = "pg16")
169))]
170#[inline]
171pub fn get_pg_version_string() -> &'static str {
172 static PG_VERSION_STR: [u8; 256] = const {
175 let major = super::PG_MAJORVERSION_NUM;
176 let minor = super::PG_MINORVERSION_NUM;
177 #[cfg(target_pointer_width = "32")]
178 let pointer_width = 32_u32;
179 #[cfg(target_pointer_width = "64")]
180 let pointer_width = 64_u32;
181 let msc_ver = b"1700";
183 let mut buffer = [0u8; 256];
184 let mut pointer = 0;
185 {
186 let s = b"PostgreSQL ";
187 let mut i = 0;
188 while i < s.len() {
189 buffer[pointer + i] = s[i];
190 i += 1;
191 }
192 pointer += s.len();
193 }
194 {
195 buffer[pointer + 0] = b'0' + (major / 10) as u8;
196 buffer[pointer + 1] = b'0' + (major % 10) as u8;
197 pointer += 2;
198 }
199 {
200 let s = b".";
201 let mut i = 0;
202 while i < s.len() {
203 buffer[pointer + i] = s[i];
204 i += 1;
205 }
206 pointer += s.len();
207 }
208 if minor < 10 {
209 buffer[pointer + 0] = b'0' + (minor % 10) as u8;
210 pointer += 1;
211 } else {
212 buffer[pointer + 0] = b'0' + (minor / 10) as u8;
213 buffer[pointer + 1] = b'0' + (minor % 10) as u8;
214 pointer += 2;
215 }
216 {
217 let s = b", compiled by Visual C++ build ";
218 let mut i = 0;
219 while i < s.len() {
220 buffer[pointer + i] = s[i];
221 i += 1;
222 }
223 pointer += s.len();
224 }
225 {
226 let s = msc_ver;
227 let mut i = 0;
228 while i < s.len() {
229 buffer[pointer + i] = s[i];
230 i += 1;
231 }
232 pointer += s.len();
233 }
234 {
235 let s = b", ";
236 let mut i = 0;
237 while i < s.len() {
238 buffer[pointer + i] = s[i];
239 i += 1;
240 }
241 pointer += s.len();
242 }
243 {
244 buffer[pointer + 0] = b'0' + (pointer_width / 10) as u8;
245 buffer[pointer + 1] = b'0' + (pointer_width % 10) as u8;
246 pointer += 2;
247 }
248 {
249 let s = b"-bit";
250 let mut i = 0;
251 while i < s.len() {
252 buffer[pointer + i] = s[i];
253 i += 1;
254 }
255 pointer += s.len();
256 }
257 buffer[pointer] = 0;
258 buffer
259 };
260 unsafe { std::ffi::CStr::from_ptr(PG_VERSION_STR.as_ptr().cast()).to_str().unwrap() }
261}
262
263#[inline]
264pub fn get_pg_major_minor_version_string() -> &'static str {
265 super::PG_VERSION.to_str().unwrap()
266}
267
268#[inline]
269pub fn TransactionIdIsNormal(xid: super::TransactionId) -> bool {
270 xid >= FirstNormalTransactionId
271}
272
273#[cfg(feature = "pg19")]
277#[inline]
278pub unsafe fn TransactionIdPrecedes(id1: super::TransactionId, id2: super::TransactionId) -> bool {
279 if !TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2) {
282 return id1 < id2;
283 }
284
285 (id1.into_inner().wrapping_sub(id2.into_inner()) as i32) < 0
286}
287
288#[cfg(feature = "pg19")]
292#[inline]
293pub unsafe fn TransactionIdPrecedesOrEquals(
294 id1: super::TransactionId,
295 id2: super::TransactionId,
296) -> bool {
297 if !TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2) {
298 return id1 <= id2;
299 }
300
301 (id1.into_inner().wrapping_sub(id2.into_inner()) as i32) <= 0
302}
303
304#[cfg(feature = "pg19")]
308#[inline]
309pub unsafe fn TransactionIdFollows(id1: super::TransactionId, id2: super::TransactionId) -> bool {
310 if !TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2) {
311 return id1 > id2;
312 }
313
314 (id1.into_inner().wrapping_sub(id2.into_inner()) as i32) > 0
315}
316
317#[cfg(feature = "pg19")]
321#[inline]
322pub unsafe fn TransactionIdFollowsOrEquals(
323 id1: super::TransactionId,
324 id2: super::TransactionId,
325) -> bool {
326 if !TransactionIdIsNormal(id1) || !TransactionIdIsNormal(id2) {
327 return id1 >= id2;
328 }
329
330 (id1.into_inner().wrapping_sub(id2.into_inner()) as i32) >= 0
331}
332
333#[inline]
337pub unsafe fn type_is_array(typoid: super::Oid) -> bool {
338 super::get_element_type(typoid) != InvalidOid
339}
340
341#[inline]
343#[cfg(any(
344 feature = "pg13",
345 feature = "pg14",
346 feature = "pg15",
347 all(
348 not(feature = "cshim"),
349 any(feature = "pg16", feature = "pg17", feature = "pg18", feature = "pg19")
350 )
351))]
352pub unsafe fn BufferGetPage(buffer: crate::Buffer) -> crate::Page {
353 BufferGetBlock(buffer) as crate::Page
354}
355
356#[inline]
365#[cfg(any(
366 feature = "pg13",
367 feature = "pg14",
368 feature = "pg15",
369 all(
370 not(feature = "cshim"),
371 any(feature = "pg16", feature = "pg17", feature = "pg18", feature = "pg19")
372 )
373))]
374pub unsafe fn BufferGetBlock(buffer: crate::Buffer) -> crate::Block {
375 if BufferIsLocal(buffer) {
376 *crate::LocalBufferBlockPointers.offset(((-buffer) - 1) as isize)
377 } else {
378 crate::BufferBlocks.add(((buffer as crate::Size) - 1) * crate::BLCKSZ as usize)
379 as crate::Block
380 }
381}
382
383#[inline]
385pub unsafe fn BufferIsLocal(buffer: crate::Buffer) -> bool {
386 buffer < 0
387}
388
389#[inline]
404pub unsafe fn heap_tuple_get_struct<T>(htup: super::HeapTuple) -> *mut T {
405 if htup.is_null() {
406 std::ptr::null_mut()
407 } else {
408 unsafe {
409 GETSTRUCT(htup).cast()
411 }
412 }
413}
414
415#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
421#[::pgrx_macros::pg_guard]
422unsafe extern "C-unwind" {
423 pub fn planstate_tree_walker(
424 planstate: *mut super::PlanState,
425 walker: ::core::option::Option<
426 unsafe extern "C-unwind" fn(*mut super::PlanState, *mut ::core::ffi::c_void) -> bool,
427 >,
428 context: *mut ::core::ffi::c_void,
429 ) -> bool;
430
431 pub fn query_tree_walker(
432 query: *mut super::Query,
433 walker: ::core::option::Option<
434 unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
435 >,
436 context: *mut ::core::ffi::c_void,
437 flags: ::core::ffi::c_int,
438 ) -> bool;
439
440 pub fn query_or_expression_tree_walker(
441 node: *mut super::Node,
442 walker: ::core::option::Option<
443 unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
444 >,
445 context: *mut ::core::ffi::c_void,
446 flags: ::core::ffi::c_int,
447 ) -> bool;
448
449 pub fn range_table_entry_walker(
450 rte: *mut super::RangeTblEntry,
451 walker: ::core::option::Option<
452 unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
453 >,
454 context: *mut ::core::ffi::c_void,
455 flags: ::core::ffi::c_int,
456 ) -> bool;
457
458 pub fn range_table_walker(
459 rtable: *mut super::List,
460 walker: ::core::option::Option<
461 unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
462 >,
463 context: *mut ::core::ffi::c_void,
464 flags: ::core::ffi::c_int,
465 ) -> bool;
466
467 pub fn expression_tree_walker(
468 node: *mut super::Node,
469 walker: ::core::option::Option<
470 unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
471 >,
472 context: *mut ::core::ffi::c_void,
473 ) -> bool;
474
475 pub fn raw_expression_tree_walker(
476 node: *mut super::Node,
477 walker: ::core::option::Option<
478 unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
479 >,
480 context: *mut ::core::ffi::c_void,
481 ) -> bool;
482}
483
484#[cfg(any(feature = "pg16", feature = "pg17", feature = "pg18", feature = "pg19"))]
485pub unsafe fn planstate_tree_walker(
486 planstate: *mut super::PlanState,
487 walker: ::core::option::Option<
488 unsafe extern "C-unwind" fn(*mut super::PlanState, *mut ::core::ffi::c_void) -> bool,
489 >,
490 context: *mut ::core::ffi::c_void,
491) -> bool {
492 crate::planstate_tree_walker_impl(planstate, walker, context)
493}
494
495#[cfg(any(feature = "pg16", feature = "pg17", feature = "pg18", feature = "pg19"))]
496pub unsafe fn query_tree_walker(
497 query: *mut super::Query,
498 walker: ::core::option::Option<
499 unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
500 >,
501 context: *mut ::core::ffi::c_void,
502 flags: ::core::ffi::c_int,
503) -> bool {
504 crate::query_tree_walker_impl(query, walker, context, flags)
505}
506
507#[cfg(any(feature = "pg16", feature = "pg17", feature = "pg18", feature = "pg19"))]
508pub unsafe fn query_or_expression_tree_walker(
509 node: *mut super::Node,
510 walker: ::core::option::Option<
511 unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
512 >,
513 context: *mut ::core::ffi::c_void,
514 flags: ::core::ffi::c_int,
515) -> bool {
516 crate::query_or_expression_tree_walker_impl(node, walker, context, flags)
517}
518
519#[cfg(any(feature = "pg16", feature = "pg17", feature = "pg18", feature = "pg19"))]
520pub unsafe fn expression_tree_walker(
521 node: *mut crate::Node,
522 walker: Option<unsafe extern "C-unwind" fn(*mut crate::Node, *mut ::core::ffi::c_void) -> bool>,
523 context: *mut ::core::ffi::c_void,
524) -> bool {
525 crate::expression_tree_walker_impl(node, walker, context)
526}
527
528#[cfg(any(feature = "pg16", feature = "pg17", feature = "pg18", feature = "pg19"))]
529pub unsafe fn range_table_entry_walker(
530 rte: *mut super::RangeTblEntry,
531 walker: ::core::option::Option<
532 unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
533 >,
534 context: *mut ::core::ffi::c_void,
535 flags: ::core::ffi::c_int,
536) -> bool {
537 crate::range_table_entry_walker_impl(rte, walker, context, flags)
538}
539
540#[cfg(any(feature = "pg16", feature = "pg17", feature = "pg18", feature = "pg19"))]
541pub unsafe fn range_table_walker(
542 rtable: *mut super::List,
543 walker: ::core::option::Option<
544 unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
545 >,
546 context: *mut ::core::ffi::c_void,
547 flags: ::core::ffi::c_int,
548) -> bool {
549 crate::range_table_walker_impl(rtable, walker, context, flags)
550}
551
552#[cfg(any(feature = "pg16", feature = "pg17", feature = "pg18", feature = "pg19"))]
553pub unsafe fn raw_expression_tree_walker(
554 node: *mut crate::Node,
555 walker: Option<unsafe extern "C-unwind" fn(*mut crate::Node, *mut ::core::ffi::c_void) -> bool>,
556 context: *mut ::core::ffi::c_void,
557) -> bool {
558 crate::raw_expression_tree_walker_impl(node, walker, context)
559}
560
561#[cfg(any(feature = "pg18", feature = "pg19"))]
562pub unsafe fn expression_tree_mutator(
563 node: *mut crate::Node,
564 mutator: crate::tree_mutator_callback,
565 context: *mut ::core::ffi::c_void,
566) -> *mut crate::Node {
567 crate::expression_tree_mutator_impl(node, mutator, context)
568}
569
570#[inline(always)]
571pub unsafe fn MemoryContextSwitchTo(context: crate::MemoryContext) -> crate::MemoryContext {
572 let old = crate::CurrentMemoryContext;
573
574 crate::CurrentMemoryContext = context;
575 old
576}
577
578#[allow(non_snake_case)]
579#[inline(always)]
580#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
581pub unsafe fn BufferGetPageSize(buffer: pg_sys::Buffer) -> pg_sys::Size {
582 assert!(BufferIsValid(buffer));
588 pg_sys::BLCKSZ as pg_sys::Size
589}
590
591#[allow(non_snake_case)]
592#[inline(always)]
593#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
594pub unsafe fn ItemIdGetOffset(item_id: pg_sys::ItemId) -> u32 {
595 (*item_id).lp_off()
598}
599
600#[allow(non_snake_case)]
601#[inline(always)]
602pub const unsafe fn PageIsValid(page: pg_sys::Page) -> bool {
603 !page.is_null()
605}
606
607#[allow(non_snake_case)]
608#[inline(always)]
609#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
610pub unsafe fn PageIsEmpty(page: pg_sys::Page) -> bool {
611 const SizeOfPageHeaderData: pg_sys::Size =
614 core::mem::offset_of!(pg_sys::PageHeaderData, pd_linp);
615 let page_header = page as *mut pg_sys::PageHeaderData;
616 (*page_header).pd_lower <= SizeOfPageHeaderData as u16
617}
618
619#[allow(non_snake_case)]
620#[inline(always)]
621#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
622pub unsafe fn PageIsNew(page: pg_sys::Page) -> bool {
623 let page_header = page as *mut pg_sys::PageHeaderData;
625 (*page_header).pd_upper == 0
626}
627
628#[allow(non_snake_case)]
629#[inline(always)]
630#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
631pub unsafe fn PageGetItemId(page: pg_sys::Page, offset: pg_sys::OffsetNumber) -> pg_sys::ItemId {
632 let page_header = page as *mut pg_sys::PageHeaderData;
635 (*page_header).pd_linp.as_mut_ptr().add(offset as usize - 1)
636}
637
638#[allow(non_snake_case)]
639#[inline(always)]
640#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
641pub unsafe fn PageGetContents(page: pg_sys::Page) -> *mut ::core::ffi::c_char {
642 const SizeOfPageHeaderData: pg_sys::Size =
645 core::mem::offset_of!(pg_sys::PageHeaderData, pd_linp);
646 page.add(pg_sys::MAXALIGN(SizeOfPageHeaderData)) as *mut ::core::ffi::c_char
647}
648
649#[allow(non_snake_case)]
650#[inline(always)]
651#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
652pub fn PageSizeIsValid(page_size: usize) -> bool {
653 page_size == pg_sys::BLCKSZ as usize
655}
656
657#[allow(non_snake_case)]
658#[inline(always)]
659#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
660pub unsafe fn PageGetPageSize(page: pg_sys::Page) -> usize {
661 let page_header = page as *mut pg_sys::PageHeaderData;
664 ((*page_header).pd_pagesize_version & 0xFF00) as usize
665}
666
667#[allow(non_snake_case)]
668#[inline(always)]
669#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
670pub unsafe fn PageGetPageLayoutVersion(page: pg_sys::Page) -> ::core::ffi::c_char {
671 let page_header = page as *mut pg_sys::PageHeaderData;
674 ((*page_header).pd_pagesize_version & 0x00FF) as ::core::ffi::c_char
675}
676
677#[allow(non_snake_case)]
678#[inline(always)]
679#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
680pub unsafe fn PageSetPageSizeAndVersion(page: pg_sys::Page, size: u16, version: u8) {
681 let page_header = page as *mut pg_sys::PageHeaderData;
684 (*page_header).pd_pagesize_version = size | (version as u16);
685}
686
687#[allow(non_snake_case)]
688#[inline(always)]
689#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
690pub unsafe fn PageGetSpecialSize(page: pg_sys::Page) -> u16 {
691 let page_header = page as *mut pg_sys::PageHeaderData;
694 PageGetPageSize(page) as u16 - (*page_header).pd_special
695}
696
697pub const unsafe fn SizeOfPageHeaderData() -> usize {
699 offset_of!(pg_sys::PageHeaderData, pd_linp)
703}
704
705#[allow(non_snake_case)]
713#[inline(always)]
714pub const unsafe fn PageValidateSpecialPointer(page: pg_sys::Page) -> bool {
715 assert!(PageIsValid(page));
725 let page = page as *mut pg_sys::PageHeaderData;
726 assert!((*page).pd_special <= BLCKSZ as _);
727 assert!((*page).pd_special >= SizeOfPageHeaderData() as _);
728 true
729}
730
731#[allow(non_snake_case)]
732#[inline(always)]
733#[cfg(any(
734 feature = "pg13",
735 feature = "pg14",
736 feature = "pg15",
737 feature = "pg18",
738 feature = "pg19"
739))]
740pub unsafe fn PageGetSpecialPointer(page: pg_sys::Page) -> *mut ::core::ffi::c_char {
741 assert!(PageValidateSpecialPointer(page));
750
751 let page_header = page as *mut pg_sys::PageHeaderData;
752 page.add((*page_header).pd_special as usize) as *mut ::core::ffi::c_char
753}
754
755#[allow(non_snake_case)]
756#[inline(always)]
757#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
758pub unsafe fn PageGetItem(page: pg_sys::Page, item_id: pg_sys::ItemId) -> *mut ::core::ffi::c_char {
759 page.add(ItemIdGetOffset(item_id) as usize)
762}
763
764#[allow(non_snake_case)]
765#[inline(always)]
766#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
767pub unsafe fn PageGetMaxOffsetNumber(page: pg_sys::Page) -> pg_sys::OffsetNumber {
768 const SizeOfPageHeaderData: pg_sys::Size =
772 core::mem::offset_of!(pg_sys::PageHeaderData, pd_linp);
773 let page_header = page as *mut pg_sys::PageHeaderData;
774 if (*page_header).pd_lower <= SizeOfPageHeaderData as u16 {
775 0
776 } else {
777 ((*page_header).pd_lower - SizeOfPageHeaderData as u16)
778 / std::mem::size_of::<pg_sys::ItemIdData>() as u16
779 }
780}
781
782#[allow(non_snake_case)]
783#[inline(always)]
784#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
785pub unsafe fn BufferIsValid(buffer: pg_sys::Buffer) -> bool {
786 assert!(buffer <= pg_sys::NBuffers);
795 assert!(buffer >= -pg_sys::NLocBuffer);
796 buffer != pg_sys::InvalidBuffer as pg_sys::Buffer
797}