#![allow(non_camel_case_types)]
use crate as pg_sys;
use crate::BuiltinOid;
use crate::Datum;
use core::fmt;
use pgx_sql_entity_graph::metadata::{
ArgumentError, Returns, ReturnsError, SqlMapping, SqlTranslatable,
};
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[derive(serde::Deserialize, serde::Serialize)]
pub struct Oid(pub(crate) u32);
impl Oid {
pub const INVALID: Oid = Oid(0);
pub const unsafe fn from_u32_unchecked(id: u32) -> Oid {
Oid(id)
}
pub const fn from_builtin(id: u32) -> Result<Oid, NotBuiltinOid> {
match BuiltinOid::from_u32(id) {
Ok(oid) => Ok(oid.value()),
Err(e) => Err(e),
}
}
pub const fn as_u32(self) -> u32 {
self.0
}
}
impl Default for Oid {
fn default() -> Oid {
Oid::INVALID
}
}
impl fmt::Display for Oid {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match PgOid::from(*self) {
PgOid::Invalid => write!(f, "oid={{#0, Invalid OID}}"),
PgOid::BuiltIn(builtin) => write!(f, "oid={{#{}, builtin: {:?}}}", self.0, builtin),
PgOid::Custom(oid) => write!(f, "oid=#{}", oid.0),
}
}
}
impl From<Oid> for u32 {
fn from(oid: Oid) -> u32 {
oid.0
}
}
impl From<Oid> for crate::Datum {
fn from(oid: Oid) -> Self {
Datum::from(oid.0)
}
}
impl From<BuiltinOid> for Oid {
fn from(builtin: BuiltinOid) -> Oid {
builtin.value()
}
}
unsafe impl SqlTranslatable for Oid {
fn argument_sql() -> Result<SqlMapping, ArgumentError> {
Ok(SqlMapping::literal("oid"))
}
fn return_sql() -> Result<Returns, ReturnsError> {
Ok(Returns::One(SqlMapping::literal("oid")))
}
}
pub type PgBuiltInOids = BuiltinOid;
pub enum NotBuiltinOid {
Invalid,
Ambiguous,
TooBig,
}
impl TryFrom<u32> for BuiltinOid {
type Error = NotBuiltinOid;
fn try_from(uint: u32) -> Result<BuiltinOid, NotBuiltinOid> {
BuiltinOid::from_u32(uint)
}
}
impl TryFrom<Oid> for BuiltinOid {
type Error = NotBuiltinOid;
fn try_from(oid: Oid) -> Result<BuiltinOid, NotBuiltinOid> {
BuiltinOid::from_u32(oid.0)
}
}
impl TryFrom<crate::Datum> for BuiltinOid {
type Error = NotBuiltinOid;
fn try_from(datum: crate::Datum) -> Result<BuiltinOid, NotBuiltinOid> {
let uint = u32::try_from(datum.value()).map_err(|_| NotBuiltinOid::TooBig)?;
BuiltinOid::from_u32(uint)
}
}
impl BuiltinOid {
pub const fn value(self) -> pg_sys::Oid {
Oid(self as u32)
}
pub fn oid(self) -> PgOid {
PgOid::from(self)
}
}
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub enum PgOid {
Invalid,
Custom(Oid),
BuiltIn(BuiltinOid),
}
impl PgOid {
pub const fn from_untagged(oid: Oid) -> PgOid {
match BuiltinOid::from_u32(oid.0) {
Ok(builtin) => PgOid::BuiltIn(builtin),
Err(NotBuiltinOid::Invalid) => PgOid::Invalid,
Err(NotBuiltinOid::Ambiguous) => PgOid::Custom(oid),
_ => unsafe { core::hint::unreachable_unchecked() },
}
}
}
impl From<BuiltinOid> for PgOid {
fn from(builtin: BuiltinOid) -> PgOid {
PgOid::BuiltIn(builtin)
}
}
impl From<Oid> for PgOid {
fn from(oid: Oid) -> PgOid {
PgOid::from_untagged(oid)
}
}
impl PgOid {
#[inline]
pub const fn value(self) -> pg_sys::Oid {
match self {
PgOid::Invalid => pg_sys::InvalidOid,
PgOid::Custom(custom) => custom,
PgOid::BuiltIn(builtin) => builtin.value(),
}
}
}