Skip to content

Commit 4bdd9b2

Browse files
committed
implement DatumPass, Element and Scalar for Uuid
1 parent 58147f1 commit 4bdd9b2

3 files changed

Lines changed: 64 additions & 1 deletion

File tree

pgrx-unit-tests/src/tests/uuid_tests.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,73 @@ fn display_uuid(uuid: Uuid) -> String {
2929
format!("{uuid}")
3030
}
3131

32+
// Exercises `Array::<Uuid>::as_slice()`, which is only available because `Uuid: Scalar`.
33+
#[pg_extern]
34+
fn uuid_array_first_via_slice(arr: Array<'_, Uuid>) -> Option<Uuid> {
35+
arr.as_slice().ok().and_then(|s| s.first().copied())
36+
}
37+
38+
// Round-trips the whole slice back into an array, exercising the `&[Uuid]` layout both ways.
39+
#[pg_extern]
40+
fn uuid_array_roundtrip_via_slice(arr: Array<'_, Uuid>) -> Vec<Uuid> {
41+
arr.as_slice().unwrap().to_vec()
42+
}
43+
3244
#[cfg(any(test, feature = "pg_test"))]
3345
#[pg_schema]
3446
mod tests {
3547
#[allow(unused_imports)]
3648
use crate as pgrx_unit_tests;
49+
use core::ptr::NonNull;
50+
use pgrx::array::{Element, Scalar};
51+
use pgrx::callconv::DatumPass;
3752
use pgrx::datum::Uuid;
53+
use pgrx::layout::PassBy;
3854
use pgrx::prelude::*;
3955

56+
// Covers every part of the `Element`/`Scalar` impls for `Uuid` that does not need a live
57+
// array: the associated OID, the pass-by-ref convention, and the identity `point_from` cast.
58+
#[pg_test]
59+
fn test_uuid_scalar_and_element_impls() {
60+
// Scalar: statically-known OID must be `uuid`.
61+
assert_eq!(<Uuid as Scalar>::OID, pg_sys::UUIDOID);
62+
63+
// DatumPass: 16 bytes > size_of::<Datum>() (8), so it must be by-reference.
64+
assert!(matches!(<Uuid as DatumPass>::PASS, PassBy::Ref));
65+
66+
// Element::point_from must be a plain identity cast (no header, no endian offset).
67+
let uuid = Uuid::from_bytes(super::TEST_UUID_V4);
68+
let ptr = NonNull::from(&uuid).cast::<u8>();
69+
let pointed = unsafe { <Uuid as Element>::point_from(ptr) };
70+
assert_eq!(pointed.as_ptr() as usize, ptr.as_ptr() as usize);
71+
// The default point_from_align4 / borrow_unchecked must observe the same bytes.
72+
let borrowed = unsafe { <Uuid as Element>::borrow_unchecked::<'_>(ptr) };
73+
assert_eq!(borrowed, &uuid);
74+
}
75+
76+
#[pg_test]
77+
fn test_uuid_array_first_via_slice() {
78+
let result = Spi::get_one::<bool>(
79+
"SELECT uuid_array_first_via_slice(\
80+
ARRAY['123e4567-e89b-12d3-a456-426614174000'::uuid, \
81+
'00000000-0000-0000-0000-000000000001'::uuid]) \
82+
= '123e4567-e89b-12d3-a456-426614174000'::uuid;",
83+
);
84+
assert_eq!(result, Ok(Some(true)));
85+
}
86+
87+
#[pg_test]
88+
fn test_uuid_array_roundtrip_via_slice() {
89+
let result = Spi::get_one::<bool>(
90+
"SELECT uuid_array_roundtrip_via_slice(\
91+
ARRAY['123e4567-e89b-12d3-a456-426614174000'::uuid, \
92+
'00000000-0000-0000-0000-000000000001'::uuid]) \
93+
= ARRAY['123e4567-e89b-12d3-a456-426614174000'::uuid, \
94+
'00000000-0000-0000-0000-000000000001'::uuid];",
95+
);
96+
assert_eq!(result, Ok(Some(true)));
97+
}
98+
4099
#[pg_test]
41100
fn test_display_uuid() {
42101
let result = Spi::get_one::<bool>(

pgrx/src/array.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,3 +438,6 @@ unsafe impl Scalar for i32 {
438438
unsafe impl Scalar for i64 {
439439
const OID: pg_sys::Oid = pg_sys::INT8OID;
440440
}
441+
unsafe impl Scalar for crate::datum::Uuid {
442+
const OID: pg_sys::Oid = pg_sys::UUIDOID;
443+
}

pgrx/src/datum/borrow.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ macro_rules! impl_borrow_fixed_len {
119119
impl_borrow_fixed_len! {
120120
i8, i16, i32, i64, bool, f32, f64,
121121
pg_sys::Oid, pg_sys::Point,
122-
Date, Time, TimeWithTimeZone, Timestamp, TimestampWithTimeZone
122+
Date, Time, TimeWithTimeZone, Timestamp, TimestampWithTimeZone,
123+
Uuid
123124
}
124125

125126
/// It is rare to pass CStr via Datums, but not unheard of

0 commit comments

Comments
 (0)