use crate::{FromDatum, IntoDatum, PgMemoryContexts, pg_sys};
use pgrx_sql_entity_graph::metadata::{
ArgumentError, ReturnsError, ReturnsRef, SqlMappingRef, SqlTranslatable,
};
#[derive(Default)]
pub struct Internal(Option<pg_sys::Datum>);
impl Internal {
#[inline(always)]
pub fn new<T>(t: T) -> Self {
Self(Some(pg_sys::Datum::from(
PgMemoryContexts::CurrentMemoryContext.leak_and_drop_on_delete(t),
)))
}
#[inline(always)]
pub fn initialized(&self) -> bool {
self.0.is_some()
}
#[inline(always)]
pub unsafe fn get<T>(&self) -> Option<&T> {
self.0.and_then(|datum| (datum.cast_mut_ptr::<T>() as *const T).as_ref())
}
#[inline(always)]
pub unsafe fn insert<T>(&mut self, value: T) -> &mut T {
let datum = pg_sys::Datum::from(
PgMemoryContexts::CurrentMemoryContext.leak_and_drop_on_delete(value),
);
let ptr = self.0.insert(datum);
&mut *(ptr.cast_mut_ptr::<T>())
}
#[inline(always)]
pub unsafe fn get_mut<T>(&mut self) -> Option<&mut T> {
self.0.and_then(|datum| (datum.cast_mut_ptr::<T>()).as_mut())
}
#[inline(always)]
pub unsafe fn get_or_insert<T>(&mut self, value: T) -> &mut T {
self.get_or_insert_with(|| value)
}
#[inline(always)]
pub unsafe fn get_or_insert_default<T>(&mut self) -> &mut T
where
T: Default,
{
self.get_or_insert_with(|| T::default())
}
#[inline(always)]
pub unsafe fn get_or_insert_with<F, T>(&mut self, f: F) -> &mut T
where
F: FnOnce() -> T,
{
let ptr = self.0.get_or_insert_with(|| {
let result = f();
PgMemoryContexts::CurrentMemoryContext.leak_and_drop_on_delete(result).into()
});
&mut *(ptr.cast_mut_ptr::<T>())
}
#[inline(always)]
pub fn unwrap(self) -> Option<pg_sys::Datum> {
self.0
}
}
impl From<Option<pg_sys::Datum>> for Internal {
#[inline]
fn from(datum: Option<pg_sys::Datum>) -> Self {
Internal(datum)
}
}
impl FromDatum for Internal {
#[inline]
unsafe fn from_polymorphic_datum(
datum: pg_sys::Datum,
is_null: bool,
_: pg_sys::Oid,
) -> Option<Internal> {
Some(Internal(if is_null { None } else { Some(datum) }))
}
}
impl IntoDatum for Internal {
#[inline]
fn into_datum(self) -> Option<pg_sys::Datum> {
self.0
}
#[inline]
fn type_oid() -> pg_sys::Oid {
pg_sys::INTERNALOID
}
}
unsafe impl SqlTranslatable for crate::datum::Internal {
const TYPE_IDENT: &'static str = crate::pgrx_resolved_type!(Internal);
const TYPE_ORIGIN: pgrx_sql_entity_graph::metadata::TypeOrigin =
pgrx_sql_entity_graph::metadata::TypeOrigin::External;
const ARGUMENT_SQL: Result<SqlMappingRef, ArgumentError> =
Ok(SqlMappingRef::literal("internal"));
const RETURN_SQL: Result<ReturnsRef, ReturnsError> =
Ok(ReturnsRef::One(SqlMappingRef::literal("internal")));
}