use crate::{
bits8, getmissingattr, heap_getsysattr, nocachegetattr, CommandId, Datum,
FormData_pg_attribute, FrozenTransactionId, HeapTupleData, HeapTupleHeaderData, TransactionId,
TupleDesc, HEAP_HASNULL, HEAP_HOT_UPDATED, HEAP_NATTS_MASK, HEAP_ONLY_TUPLE, HEAP_XMAX_INVALID,
HEAP_XMIN_COMMITTED, HEAP_XMIN_FROZEN, HEAP_XMIN_INVALID, SIZEOF_DATUM,
};
#[inline(always)]
pub unsafe fn HeapTupleHeaderIsHeapOnly(tup: *const HeapTupleHeaderData) -> bool {
unsafe {
((*tup).t_infomask2 & HEAP_ONLY_TUPLE as u16) != 0
}
}
#[inline(always)]
pub unsafe fn HeapTupleHeaderIsHotUpdated(tup: *const HeapTupleHeaderData) -> bool {
unsafe {
(*tup).t_infomask2 & HEAP_HOT_UPDATED as u16 != 0
&& (*tup).t_infomask & HEAP_XMAX_INVALID as u16 == 0
&& !HeapTupleHeaderXminInvalid(tup)
}
}
#[inline(always)]
pub unsafe fn HeapTupleHeaderXminInvalid(tup: *const HeapTupleHeaderData) -> bool {
unsafe {
(*tup).t_infomask & (HEAP_XMIN_COMMITTED as u16 | HEAP_XMIN_INVALID as u16)
== HEAP_XMIN_INVALID as u16
}
}
#[inline(always)]
pub unsafe fn HeapTupleHeaderFrozen(tup: *const HeapTupleHeaderData) -> bool {
unsafe {
(*tup).t_infomask & (HEAP_XMIN_FROZEN as u16) == (HEAP_XMIN_FROZEN as u16)
}
}
#[inline(always)]
pub unsafe fn HeapTupleGetRawCommandId(tup: *const HeapTupleHeaderData) -> CommandId {
unsafe {
(*tup).t_choice.t_heap.t_field3.t_cid
}
}
#[inline(always)]
pub unsafe fn HeapTupleHeaderGetRawXmin(tup: *const HeapTupleHeaderData) -> TransactionId {
unsafe {
(*tup).t_choice.t_heap.t_xmin
}
}
#[inline(always)]
pub unsafe fn HeapTupleHeaderGetXmin(tup: *const HeapTupleHeaderData) -> TransactionId {
unsafe {
if HeapTupleHeaderFrozen(tup) {
FrozenTransactionId
} else {
HeapTupleHeaderGetRawXmin(tup)
}
}
}
#[inline(always)]
pub unsafe fn HeapTupleHeaderGetNatts(tup: *const HeapTupleHeaderData) -> u16 {
unsafe {
(*tup).t_infomask2 & (HEAP_NATTS_MASK as u16)
}
}
#[inline(always)]
pub unsafe fn HeapTupleNoNulls(tup: *const HeapTupleData) -> bool {
unsafe {
(*(*tup).t_data).t_infomask & (HEAP_HASNULL as u16) == 0
}
}
#[inline(always)]
unsafe fn att_isnull(ATT: i32, BITS: *const bits8) -> bool {
let ATT = ATT as usize;
let slot = BITS.add(ATT >> 3);
(*slot & (1 << (ATT & 0x07))) == 0
}
#[inline(always)]
unsafe fn fetchatt(A: *const FormData_pg_attribute, T: *mut std::os::raw::c_char) -> Datum {
unsafe {
fetch_att(T, (*A).attbyval, (*A).attlen)
}
}
#[inline(always)]
unsafe fn fetch_att(T: *mut std::os::raw::c_char, attbyval: bool, attlen: i16) -> Datum {
unsafe {
if attbyval {
let attlen = attlen as usize;
if SIZEOF_DATUM == 8 {
if attlen == std::mem::size_of::<Datum>() {
return *T.cast::<Datum>();
}
}
if attlen == std::mem::size_of::<i32>() {
Datum::from(*T.cast::<i32>())
} else {
if attlen == std::mem::size_of::<i16>() {
Datum::from(*T.cast::<i16>())
} else {
assert_eq!(attlen, 1);
Datum::from(*T.cast::<std::os::raw::c_char>())
}
}
} else {
Datum::from(T.cast::<std::os::raw::c_char>())
}
}
}
#[inline(always)]
pub unsafe fn heap_getattr(
tup: *mut HeapTupleData,
attnum: i32,
tupleDesc: TupleDesc,
isnull: &mut bool,
) -> Datum {
unsafe {
if attnum > 0 {
if attnum > HeapTupleHeaderGetNatts((*tup).t_data) as i32 {
getmissingattr(tupleDesc, attnum, isnull)
} else {
fastgetattr(tup, attnum, tupleDesc, isnull)
}
} else {
heap_getsysattr(tup, attnum, tupleDesc, isnull)
}
}
}
#[inline(always)]
unsafe fn fastgetattr(
tup: *mut HeapTupleData,
attnum: i32,
tupleDesc: TupleDesc,
isnull: &mut bool,
) -> Datum {
assert!(attnum > 0);
unsafe {
*isnull = false;
if HeapTupleNoNulls(tup) {
let att = &(*tupleDesc).attrs.as_slice((*tupleDesc).natts as _)[attnum as usize - 1];
if att.attcacheoff >= 0 {
let t_data = (*tup).t_data;
fetchatt(
att,
t_data
.cast::<std::os::raw::c_char>()
.add((*t_data).t_hoff as usize + att.attcacheoff as usize),
)
} else {
nocachegetattr(tup, attnum, tupleDesc)
}
} else {
if att_isnull(attnum - 1, (*(*tup).t_data).t_bits.as_ptr()) {
*isnull = true;
Datum::from(0) } else {
nocachegetattr(tup, attnum, tupleDesc)
}
}
}
}