@@ -57,6 +57,8 @@ use vortex::extension::datetime::TemporalMetadata;
5757use vortex:: extension:: datetime:: Time ;
5858use vortex:: extension:: datetime:: TimeUnit ;
5959use vortex:: extension:: datetime:: Timestamp ;
60+ use vortex:: extension:: uuid:: Uuid ;
61+ use vortex:: extension:: uuid:: UuidMetadata ;
6062use vortex_spatial:: extension:: LineString ;
6163use vortex_spatial:: extension:: MultiLineString ;
6264use vortex_spatial:: extension:: MultiPoint ;
@@ -180,11 +182,18 @@ impl FromLogicalType for DType {
180182 )
181183 }
182184 DUCKDB_TYPE :: DUCKDB_TYPE_VARIANT => DType :: Variant ( nullability) ,
185+ DUCKDB_TYPE :: DUCKDB_TYPE_UUID => DType :: Extension (
186+ ExtDType :: < Uuid > :: try_with_vtable (
187+ Uuid ,
188+ UuidMetadata :: default ( ) ,
189+ uuid_storage_dtype ( nullability) ,
190+ ) ?
191+ . erased ( ) ,
192+ ) ,
183193 other @ ( DUCKDB_TYPE :: DUCKDB_TYPE_TIME_TZ
184194 | DUCKDB_TYPE :: DUCKDB_TYPE_INTERVAL
185195 | DUCKDB_TYPE :: DUCKDB_TYPE_ENUM
186196 | DUCKDB_TYPE :: DUCKDB_TYPE_MAP
187- | DUCKDB_TYPE :: DUCKDB_TYPE_UUID
188197 | DUCKDB_TYPE :: DUCKDB_TYPE_UNION
189198 | DUCKDB_TYPE :: DUCKDB_TYPE_BIT
190199 | DUCKDB_TYPE :: DUCKDB_TYPE_ANY
@@ -254,6 +263,10 @@ impl TryFrom<&DType> for LogicalType {
254263 return temporal_to_duckdb ( temporal) ;
255264 }
256265
266+ if ext_dtype. is :: < Uuid > ( ) {
267+ return Ok ( LogicalType :: new ( DUCKDB_TYPE :: DUCKDB_TYPE_UUID ) ) ;
268+ }
269+
257270 // Native geometry types and WKB all surface to DuckDB as GEOMETRY so `ST_*` bind.
258271 if let Some ( spatial_metadata) = ext_dtype
259272 . metadata_opt :: < Point > ( )
@@ -275,6 +288,14 @@ impl TryFrom<&DType> for LogicalType {
275288 }
276289}
277290
291+ fn uuid_storage_dtype ( nullability : Nullability ) -> DType {
292+ DType :: FixedSizeList (
293+ Arc :: new ( DType :: Primitive ( U8 , Nullability :: NonNullable ) ) ,
294+ 16 ,
295+ nullability,
296+ )
297+ }
298+
278299fn temporal_to_duckdb ( temporal : TemporalMetadata ) -> VortexResult < LogicalType > {
279300 let duckdb_type = match temporal {
280301 TemporalMetadata :: Timestamp ( unit, None ) => match unit {
@@ -637,6 +658,31 @@ mod tests {
637658 Ok ( ( ) )
638659 }
639660
661+ #[ rstest]
662+ #[ case( Nullability :: NonNullable ) ]
663+ #[ case( Nullability :: Nullable ) ]
664+ fn test_uuid_roundtrip ( #[ case] nullability : Nullability ) -> VortexResult < ( ) > {
665+ use vortex:: extension:: uuid:: Uuid ;
666+ use vortex:: extension:: uuid:: UuidMetadata ;
667+
668+ let storage = DType :: FixedSizeList (
669+ Arc :: new ( DType :: Primitive ( PType :: U8 , Nullability :: NonNullable ) ) ,
670+ 16 ,
671+ nullability,
672+ ) ;
673+ let vortex_uuid = DType :: Extension (
674+ ExtDType :: < Uuid > :: try_with_vtable ( Uuid , UuidMetadata :: default ( ) , storage) ?. erased ( ) ,
675+ ) ;
676+
677+ let duckdb_uuid = LogicalType :: try_from ( & vortex_uuid) ?;
678+ assert_eq ! ( duckdb_uuid. as_type_id( ) , cpp:: DUCKDB_TYPE :: DUCKDB_TYPE_UUID ) ;
679+
680+ let original = DType :: from_logical_type ( & duckdb_uuid, nullability) ?;
681+ assert_eq ! ( original, vortex_uuid) ;
682+
683+ Ok ( ( ) )
684+ }
685+
640686 #[ test]
641687 fn test_unsupported_extension_type ( ) {
642688 #[ derive( Clone , Debug , Default , PartialEq , Eq , Hash ) ]
0 commit comments