Skip to content

Commit

Permalink
Added oids_of! macro (#1879)
Browse files Browse the repository at this point in the history
That's an improvement for SPI making it less cumbersome. Just to feel
the difference look at the tests. Who would really want to write
something like `PgBuiltInOids::INT4OID.oid()` instead of just telling a
Rust type?
  • Loading branch information
YohDeadfall authored Nov 25, 2024
1 parent a0ecc8f commit eda7549
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 18 deletions.
19 changes: 6 additions & 13 deletions pgrx-tests/src/tests/spi_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ mod tests {
use std::error::Error;

use pgrx::prelude::*;
use pgrx::spi;
use pgrx::spi::Query;
use pgrx::spi::{self, Query};

#[pg_test(error = "syntax error at or near \"THIS\"")]
fn test_spi_failure() -> Result<(), spi::Error> {
Expand Down Expand Up @@ -253,10 +252,8 @@ mod tests {
None,
&[],
)?;
let prepared = client.prepare(
"SELECT * FROM tests.cursor_table WHERE id = $1",
&[PgBuiltInOids::INT4OID.oid()],
)?;
let prepared =
client.prepare("SELECT * FROM tests.cursor_table WHERE id = $1", &oids_of![i32])?;
client.open_cursor(&prepared, args);
unreachable!();
})
Expand Down Expand Up @@ -376,8 +373,7 @@ mod tests {
#[pg_test]
fn test_prepared_statement() -> Result<(), spi::Error> {
let rc = Spi::connect(|client| {
let prepared =
client.prepare("SELECT $1", &[PgOid::BuiltIn(PgBuiltInOids::INT4OID)])?;
let prepared = client.prepare("SELECT $1", &oids_of![i32])?;
client.select(&prepared, None, &[42.into()])?.first().get::<i32>(1)
})?;

Expand All @@ -388,8 +384,7 @@ mod tests {
#[pg_test]
fn test_prepared_statement_argument_mismatch() {
let err = Spi::connect(|client| {
let prepared =
client.prepare("SELECT $1", &[PgOid::BuiltIn(PgBuiltInOids::INT4OID)])?;
let prepared = client.prepare("SELECT $1", &oids_of![i32])?;
client.select(&prepared, None, &[]).map(|_| ())
})
.unwrap_err();
Expand All @@ -403,9 +398,7 @@ mod tests {
#[pg_test]
fn test_owned_prepared_statement() -> Result<(), spi::Error> {
let prepared = Spi::connect(|client| {
Ok::<_, spi::Error>(
client.prepare("SELECT $1", &[PgOid::BuiltIn(PgBuiltInOids::INT4OID)])?.keep(),
)
Ok::<_, spi::Error>(client.prepare("SELECT $1", &oids_of![i32])?.keep())
})?;
let rc = Spi::connect(|client| {
client.select(&prepared, None, &[42.into()])?.first().get::<i32>(1)
Expand Down
27 changes: 27 additions & 0 deletions pgrx/src/datum/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,30 @@ impl<'src, T: IntoDatum> From<T> for DatumWithOid<'src> {
/// A tagging trait to indicate a user type is also meant to be used by Postgres
/// Implemented automatically by `#[derive(PostgresType)]`
pub trait PostgresType {}

/// Creates an array of [`pg_sys::Oid`] with the OID of each provided type
///
/// # Examples
///
/// ```
/// use pgrx::{oids_of, datum::IntoDatum};
///
/// let oids = oids_of![i32, f64];
/// assert_eq!(oids[0], i32::type_oid().into());
/// assert_eq!(oids[1], f64::type_oid().into());
///
/// // the usual conversions or coercions are available
/// let oid_vec = oids_of![i8, i16].to_vec();
/// let no_oid = &oids_of![];
/// assert_eq!(no_oid.len(), 0);
/// ```
#[macro_export]
macro_rules! oids_of {
() =>(
// avoid coercions to an ambiguously-typed array or slice
[$crate::pg_sys::PgOid::Invalid; 0]
);
($($t:path),+ $(,)?) => (
[$($crate::pg_sys::PgOid::from(<$t>::type_oid())),*]
);
}
13 changes: 8 additions & 5 deletions pgrx/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@ pub use crate::pgbox::{AllocatedByPostgres, AllocatedByRust, PgBox, WhoAllocated
// These could be factored into a temporal type module that could be easily imported for code which works with them.
// However, reexporting them seems fine for now.

pub use crate::datum::{
datetime_support::*, AnyNumeric, Array, ArraySliceError, Date, FromDatum, Interval, IntoDatum,
Numeric, PgVarlena, PostgresType, Range, RangeBound, RangeSubType, Time, TimeWithTimeZone,
Timestamp, TimestampWithTimeZone, VariadicArray,
};
pub use crate::inoutfuncs::{InOutFuncs, PgVarlenaInOutFuncs};
pub use crate::{
datum::{
datetime_support::*, AnyNumeric, Array, ArraySliceError, Date, FromDatum, Interval,
IntoDatum, Numeric, PgVarlena, PostgresType, Range, RangeBound, RangeSubType, Time,
TimeWithTimeZone, Timestamp, TimestampWithTimeZone, VariadicArray,
},
oids_of,
};

// Trigger support
pub use crate::trigger_support::{
Expand Down

0 comments on commit eda7549

Please sign in to comment.