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"))]
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"))]
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#[inline]
277pub unsafe fn type_is_array(typoid: super::Oid) -> bool {
278 super::get_element_type(typoid) != InvalidOid
279}
280
281#[inline]
283pub unsafe fn BufferGetPage(buffer: crate::Buffer) -> crate::Page {
284 BufferGetBlock(buffer) as crate::Page
285}
286
287#[inline]
296pub unsafe fn BufferGetBlock(buffer: crate::Buffer) -> crate::Block {
297 if BufferIsLocal(buffer) {
298 *crate::LocalBufferBlockPointers.offset(((-buffer) - 1) as isize)
299 } else {
300 crate::BufferBlocks.add(((buffer as crate::Size) - 1) * crate::BLCKSZ as usize)
301 as crate::Block
302 }
303}
304
305#[inline]
307pub unsafe fn BufferIsLocal(buffer: crate::Buffer) -> bool {
308 buffer < 0
309}
310
311#[inline]
326pub unsafe fn heap_tuple_get_struct<T>(htup: super::HeapTuple) -> *mut T {
327 if htup.is_null() {
328 std::ptr::null_mut()
329 } else {
330 unsafe {
331 GETSTRUCT(htup).cast()
333 }
334 }
335}
336
337#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
343#[::pgrx_macros::pg_guard]
344extern "C-unwind" {
345 pub fn planstate_tree_walker(
346 planstate: *mut super::PlanState,
347 walker: ::core::option::Option<
348 unsafe extern "C-unwind" fn(*mut super::PlanState, *mut ::core::ffi::c_void) -> bool,
349 >,
350 context: *mut ::core::ffi::c_void,
351 ) -> bool;
352
353 pub fn query_tree_walker(
354 query: *mut super::Query,
355 walker: ::core::option::Option<
356 unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
357 >,
358 context: *mut ::core::ffi::c_void,
359 flags: ::core::ffi::c_int,
360 ) -> bool;
361
362 pub fn query_or_expression_tree_walker(
363 node: *mut super::Node,
364 walker: ::core::option::Option<
365 unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
366 >,
367 context: *mut ::core::ffi::c_void,
368 flags: ::core::ffi::c_int,
369 ) -> bool;
370
371 pub fn range_table_entry_walker(
372 rte: *mut super::RangeTblEntry,
373 walker: ::core::option::Option<
374 unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
375 >,
376 context: *mut ::core::ffi::c_void,
377 flags: ::core::ffi::c_int,
378 ) -> bool;
379
380 pub fn range_table_walker(
381 rtable: *mut super::List,
382 walker: ::core::option::Option<
383 unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
384 >,
385 context: *mut ::core::ffi::c_void,
386 flags: ::core::ffi::c_int,
387 ) -> bool;
388
389 pub fn expression_tree_walker(
390 node: *mut super::Node,
391 walker: ::core::option::Option<
392 unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
393 >,
394 context: *mut ::core::ffi::c_void,
395 ) -> bool;
396
397 pub fn raw_expression_tree_walker(
398 node: *mut super::Node,
399 walker: ::core::option::Option<
400 unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
401 >,
402 context: *mut ::core::ffi::c_void,
403 ) -> bool;
404}
405
406#[cfg(any(feature = "pg16", feature = "pg17", feature = "pg18"))]
407pub unsafe fn planstate_tree_walker(
408 planstate: *mut super::PlanState,
409 walker: ::core::option::Option<
410 unsafe extern "C-unwind" fn(*mut super::PlanState, *mut ::core::ffi::c_void) -> bool,
411 >,
412 context: *mut ::core::ffi::c_void,
413) -> bool {
414 crate::planstate_tree_walker_impl(planstate, walker, context)
415}
416
417#[cfg(any(feature = "pg16", feature = "pg17", feature = "pg18"))]
418pub unsafe fn query_tree_walker(
419 query: *mut super::Query,
420 walker: ::core::option::Option<
421 unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
422 >,
423 context: *mut ::core::ffi::c_void,
424 flags: ::core::ffi::c_int,
425) -> bool {
426 crate::query_tree_walker_impl(query, walker, context, flags)
427}
428
429#[cfg(any(feature = "pg16", feature = "pg17", feature = "pg18"))]
430pub unsafe fn query_or_expression_tree_walker(
431 node: *mut super::Node,
432 walker: ::core::option::Option<
433 unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
434 >,
435 context: *mut ::core::ffi::c_void,
436 flags: ::core::ffi::c_int,
437) -> bool {
438 crate::query_or_expression_tree_walker_impl(node, walker, context, flags)
439}
440
441#[cfg(any(feature = "pg16", feature = "pg17", feature = "pg18"))]
442pub unsafe fn expression_tree_walker(
443 node: *mut crate::Node,
444 walker: Option<unsafe extern "C-unwind" fn(*mut crate::Node, *mut ::core::ffi::c_void) -> bool>,
445 context: *mut ::core::ffi::c_void,
446) -> bool {
447 crate::expression_tree_walker_impl(node, walker, context)
448}
449
450#[cfg(any(feature = "pg16", feature = "pg17", feature = "pg18"))]
451pub unsafe fn range_table_entry_walker(
452 rte: *mut super::RangeTblEntry,
453 walker: ::core::option::Option<
454 unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
455 >,
456 context: *mut ::core::ffi::c_void,
457 flags: ::core::ffi::c_int,
458) -> bool {
459 crate::range_table_entry_walker_impl(rte, walker, context, flags)
460}
461
462#[cfg(any(feature = "pg16", feature = "pg17", feature = "pg18"))]
463pub unsafe fn range_table_walker(
464 rtable: *mut super::List,
465 walker: ::core::option::Option<
466 unsafe extern "C-unwind" fn(*mut super::Node, *mut ::core::ffi::c_void) -> bool,
467 >,
468 context: *mut ::core::ffi::c_void,
469 flags: ::core::ffi::c_int,
470) -> bool {
471 crate::range_table_walker_impl(rtable, walker, context, flags)
472}
473
474#[cfg(any(feature = "pg16", feature = "pg17", feature = "pg18"))]
475pub unsafe fn raw_expression_tree_walker(
476 node: *mut crate::Node,
477 walker: Option<unsafe extern "C-unwind" fn(*mut crate::Node, *mut ::core::ffi::c_void) -> bool>,
478 context: *mut ::core::ffi::c_void,
479) -> bool {
480 crate::raw_expression_tree_walker_impl(node, walker, context)
481}
482
483#[cfg(feature = "pg18")]
484pub unsafe fn expression_tree_mutator(
485 node: *mut crate::Node,
486 mutator: crate::tree_mutator_callback,
487 context: *mut ::core::ffi::c_void,
488) -> *mut crate::Node {
489 crate::expression_tree_mutator_impl(node, mutator, context)
490}
491
492#[inline(always)]
493pub unsafe fn MemoryContextSwitchTo(context: crate::MemoryContext) -> crate::MemoryContext {
494 let old = crate::CurrentMemoryContext;
495
496 crate::CurrentMemoryContext = context;
497 old
498}
499
500#[allow(non_snake_case)]
501#[inline(always)]
502#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
503pub unsafe fn BufferGetPageSize(buffer: pg_sys::Buffer) -> pg_sys::Size {
504 assert!(BufferIsValid(buffer));
510 pg_sys::BLCKSZ as pg_sys::Size
511}
512
513#[allow(non_snake_case)]
514#[inline(always)]
515#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
516pub unsafe fn ItemIdGetOffset(item_id: pg_sys::ItemId) -> u32 {
517 (*item_id).lp_off()
520}
521
522#[allow(non_snake_case)]
523#[inline(always)]
524pub const unsafe fn PageIsValid(page: pg_sys::Page) -> bool {
525 !page.is_null()
527}
528
529#[allow(non_snake_case)]
530#[inline(always)]
531#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
532pub unsafe fn PageIsEmpty(page: pg_sys::Page) -> bool {
533 const SizeOfPageHeaderData: pg_sys::Size =
536 core::mem::offset_of!(pg_sys::PageHeaderData, pd_linp);
537 let page_header = page as *mut pg_sys::PageHeaderData;
538 (*page_header).pd_lower <= SizeOfPageHeaderData as u16
539}
540
541#[allow(non_snake_case)]
542#[inline(always)]
543#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
544pub unsafe fn PageIsNew(page: pg_sys::Page) -> bool {
545 let page_header = page as *mut pg_sys::PageHeaderData;
547 (*page_header).pd_upper == 0
548}
549
550#[allow(non_snake_case)]
551#[inline(always)]
552#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
553pub unsafe fn PageGetItemId(page: pg_sys::Page, offset: pg_sys::OffsetNumber) -> pg_sys::ItemId {
554 let page_header = page as *mut pg_sys::PageHeaderData;
557 (*page_header).pd_linp.as_mut_ptr().add(offset as usize - 1)
558}
559
560#[allow(non_snake_case)]
561#[inline(always)]
562#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
563pub unsafe fn PageGetContents(page: pg_sys::Page) -> *mut ::core::ffi::c_char {
564 const SizeOfPageHeaderData: pg_sys::Size =
567 core::mem::offset_of!(pg_sys::PageHeaderData, pd_linp);
568 page.add(pg_sys::MAXALIGN(SizeOfPageHeaderData)) as *mut ::core::ffi::c_char
569}
570
571#[allow(non_snake_case)]
572#[inline(always)]
573#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
574pub fn PageSizeIsValid(page_size: usize) -> bool {
575 page_size == pg_sys::BLCKSZ as usize
577}
578
579#[allow(non_snake_case)]
580#[inline(always)]
581#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
582pub unsafe fn PageGetPageSize(page: pg_sys::Page) -> usize {
583 let page_header = page as *mut pg_sys::PageHeaderData;
586 ((*page_header).pd_pagesize_version & 0xFF00) as usize
587}
588
589#[allow(non_snake_case)]
590#[inline(always)]
591#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
592pub unsafe fn PageGetPageLayoutVersion(page: pg_sys::Page) -> ::core::ffi::c_char {
593 let page_header = page as *mut pg_sys::PageHeaderData;
596 ((*page_header).pd_pagesize_version & 0x00FF) as ::core::ffi::c_char
597}
598
599#[allow(non_snake_case)]
600#[inline(always)]
601#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
602pub unsafe fn PageSetPageSizeAndVersion(page: pg_sys::Page, size: u16, version: u8) {
603 let page_header = page as *mut pg_sys::PageHeaderData;
606 (*page_header).pd_pagesize_version = size | (version as u16);
607}
608
609#[allow(non_snake_case)]
610#[inline(always)]
611#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
612pub unsafe fn PageGetSpecialSize(page: pg_sys::Page) -> u16 {
613 let page_header = page as *mut pg_sys::PageHeaderData;
616 PageGetPageSize(page) as u16 - (*page_header).pd_special
617}
618
619pub const unsafe fn SizeOfPageHeaderData() -> usize {
621 offset_of!(pg_sys::PageHeaderData, pd_linp)
625}
626
627#[allow(non_snake_case)]
635#[inline(always)]
636pub const unsafe fn PageValidateSpecialPointer(page: pg_sys::Page) -> bool {
637 assert!(PageIsValid(page));
647 let page = page as *mut pg_sys::PageHeaderData;
648 assert!((*page).pd_special <= BLCKSZ as _);
649 assert!((*page).pd_special >= SizeOfPageHeaderData() as _);
650 true
651}
652
653#[allow(non_snake_case)]
654#[inline(always)]
655#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15", feature = "pg18"))]
656pub unsafe fn PageGetSpecialPointer(page: pg_sys::Page) -> *mut ::core::ffi::c_char {
657 assert!(PageValidateSpecialPointer(page));
666
667 let page_header = page as *mut pg_sys::PageHeaderData;
668 page.add((*page_header).pd_special as usize) as *mut ::core::ffi::c_char
669}
670
671#[allow(non_snake_case)]
672#[inline(always)]
673#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
674pub unsafe fn PageGetItem(page: pg_sys::Page, item_id: pg_sys::ItemId) -> *mut ::core::ffi::c_char {
675 page.add(ItemIdGetOffset(item_id) as usize)
678}
679
680#[allow(non_snake_case)]
681#[inline(always)]
682#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
683pub unsafe fn PageGetMaxOffsetNumber(page: pg_sys::Page) -> pg_sys::OffsetNumber {
684 const SizeOfPageHeaderData: pg_sys::Size =
688 core::mem::offset_of!(pg_sys::PageHeaderData, pd_linp);
689 let page_header = page as *mut pg_sys::PageHeaderData;
690 if (*page_header).pd_lower <= SizeOfPageHeaderData as u16 {
691 0
692 } else {
693 ((*page_header).pd_lower - SizeOfPageHeaderData as u16)
694 / std::mem::size_of::<pg_sys::ItemIdData>() as u16
695 }
696}
697
698#[allow(non_snake_case)]
699#[inline(always)]
700#[cfg(any(feature = "pg13", feature = "pg14", feature = "pg15"))]
701pub unsafe fn BufferIsValid(buffer: pg_sys::Buffer) -> bool {
702 assert!(buffer <= pg_sys::NBuffers);
711 assert!(buffer >= -pg_sys::NLocBuffer);
712 buffer != pg_sys::InvalidBuffer as pg_sys::Buffer
713}