@@ -93,7 +93,7 @@ impl LogicalType {
9393 unsafe {
9494 let ptr = cpp:: duckdb_create_list_type ( element_type. as_ptr ( ) ) ;
9595 if ptr. is_null ( ) {
96- return Err ( vortex_err ! ( "Failed to create list type" ) ) ;
96+ vortex_bail ! ( "Failed to create list type" ) ;
9797 }
9898 Ok ( Self :: own ( ptr) )
9999 }
@@ -119,24 +119,28 @@ impl LogicalType {
119119 let duckdb_type = match temporal_metadata {
120120 TemporalMetadata :: Date ( TimeUnit :: D ) => DUCKDB_TYPE :: DUCKDB_TYPE_DATE ,
121121 TemporalMetadata :: Date ( time_unit) => {
122- return Err ( vortex_err ! ( "Invalid TimeUnit {} for date" , time_unit) ) ;
122+ vortex_bail ! ( "Invalid TimeUnit {} for date" , time_unit) ;
123123 }
124124 TemporalMetadata :: Time ( TimeUnit :: Us ) => DUCKDB_TYPE :: DUCKDB_TYPE_TIME ,
125125 TemporalMetadata :: Time ( time_unit) => {
126- return Err ( vortex_err ! ( "Invalid TimeUnit {} for time" , time_unit) ) ;
126+ vortex_bail ! ( "Invalid TimeUnit {} for time" , time_unit) ;
127127 }
128- TemporalMetadata :: Timestamp ( time_unit, tz) => {
129- if tz. is_some ( ) {
130- return Err ( vortex_err ! ( "Timestamp with timezone is not yet supported" ) ) ;
128+ TemporalMetadata :: Timestamp ( time_unit, tz) => match time_unit {
129+ TimeUnit :: Ns => DUCKDB_TYPE :: DUCKDB_TYPE_TIMESTAMP_NS ,
130+ TimeUnit :: Us => {
131+ if let Some ( tz) = tz {
132+ if tz != "UTC" {
133+ vortex_bail ! ( "Invalid timezone for timestamp: {tz}" ) ;
134+ }
135+ DUCKDB_TYPE :: DUCKDB_TYPE_TIMESTAMP_TZ
136+ } else {
137+ DUCKDB_TYPE :: DUCKDB_TYPE_TIMESTAMP
138+ }
131139 }
132- match time_unit {
133- TimeUnit :: Ns => DUCKDB_TYPE :: DUCKDB_TYPE_TIMESTAMP_NS ,
134- TimeUnit :: Us => DUCKDB_TYPE :: DUCKDB_TYPE_TIMESTAMP ,
135- TimeUnit :: Ms => DUCKDB_TYPE :: DUCKDB_TYPE_TIMESTAMP_MS ,
136- TimeUnit :: S => DUCKDB_TYPE :: DUCKDB_TYPE_TIMESTAMP_S ,
137- _ => return Err ( vortex_err ! ( "Invalid TimeUnit {} for timestamp" , time_unit) ) ,
138- }
139- }
140+ TimeUnit :: Ms => DUCKDB_TYPE :: DUCKDB_TYPE_TIMESTAMP_MS ,
141+ TimeUnit :: S => DUCKDB_TYPE :: DUCKDB_TYPE_TIMESTAMP_S ,
142+ _ => vortex_bail ! ( "Invalid TimeUnit {} for timestamp" , time_unit) ,
143+ } ,
140144 } ;
141145
142146 Ok ( Self :: new ( duckdb_type) )
@@ -171,7 +175,6 @@ impl FromLogicalType for DType {
171175 DUCKDB_TYPE :: DUCKDB_TYPE_UHUGEINT => todo ! ( ) ,
172176 DUCKDB_TYPE :: DUCKDB_TYPE_FLOAT => DType :: Primitive ( F32 , nullability) ,
173177 DUCKDB_TYPE :: DUCKDB_TYPE_DOUBLE => DType :: Primitive ( F64 , nullability) ,
174-
175178 DUCKDB_TYPE :: DUCKDB_TYPE_VARCHAR => DType :: Utf8 ( nullability) ,
176179 DUCKDB_TYPE :: DUCKDB_TYPE_BLOB => DType :: Binary ( nullability) ,
177180 DUCKDB_TYPE :: DUCKDB_TYPE_DECIMAL => {
@@ -206,11 +209,17 @@ impl FromLogicalType for DType {
206209 Arc :: new ( DType :: Primitive ( I64 , nullability) ) ,
207210 Some ( TemporalMetadata :: Timestamp ( TimeUnit :: Us , None ) . into ( ) ) ,
208211 ) ) ) ,
212+ DUCKDB_TYPE :: DUCKDB_TYPE_TIMESTAMP_TZ => DType :: Extension ( Arc :: new ( ExtDType :: new (
213+ TIMESTAMP_ID . clone ( ) ,
214+ Arc :: new ( DType :: Primitive ( I64 , nullability) ) ,
215+ Some ( TemporalMetadata :: Timestamp ( TimeUnit :: Us , Some ( "UTC" . to_string ( ) ) ) . into ( ) ) ,
216+ ) ) ) ,
209217 DUCKDB_TYPE :: DUCKDB_TYPE_TIMESTAMP_NS => DType :: Extension ( Arc :: new ( ExtDType :: new (
210218 TIMESTAMP_ID . clone ( ) ,
211219 Arc :: new ( DType :: Primitive ( I64 , nullability) ) ,
212220 Some ( TemporalMetadata :: Timestamp ( TimeUnit :: Ns , None ) . into ( ) ) ,
213221 ) ) ) ,
222+ DUCKDB_TYPE :: DUCKDB_TYPE_TIME_TZ => todo ! ( ) ,
214223 DUCKDB_TYPE :: DUCKDB_TYPE_INTERVAL => todo ! ( ) ,
215224 DUCKDB_TYPE :: DUCKDB_TYPE_ENUM => todo ! ( ) ,
216225 DUCKDB_TYPE :: DUCKDB_TYPE_LIST => todo ! ( ) ,
@@ -220,8 +229,6 @@ impl FromLogicalType for DType {
220229 DUCKDB_TYPE :: DUCKDB_TYPE_UUID => todo ! ( ) ,
221230 DUCKDB_TYPE :: DUCKDB_TYPE_UNION => todo ! ( ) ,
222231 DUCKDB_TYPE :: DUCKDB_TYPE_BIT => todo ! ( ) ,
223- DUCKDB_TYPE :: DUCKDB_TYPE_TIME_TZ => todo ! ( ) ,
224- DUCKDB_TYPE :: DUCKDB_TYPE_TIMESTAMP_TZ => todo ! ( ) ,
225232 DUCKDB_TYPE :: DUCKDB_TYPE_ANY => todo ! ( ) ,
226233 DUCKDB_TYPE :: DUCKDB_TYPE_VARINT => todo ! ( ) ,
227234 DUCKDB_TYPE :: DUCKDB_TYPE_STRING_LITERAL => todo ! ( ) ,
@@ -526,6 +533,26 @@ mod tests {
526533 }
527534 }
528535
536+ #[ test]
537+ fn test_timestamp_with_timezone ( ) {
538+ use std:: sync:: Arc ;
539+
540+ use vortex:: dtype:: datetime:: { TIMESTAMP_ID , TemporalMetadata , TimeUnit } ;
541+ use vortex:: dtype:: { ExtDType , PType } ;
542+
543+ let ext_dtype = ExtDType :: new (
544+ TIMESTAMP_ID . clone ( ) ,
545+ Arc :: new ( DType :: Primitive ( PType :: I64 , Nullability :: NonNullable ) ) ,
546+ Some ( TemporalMetadata :: Timestamp ( TimeUnit :: Us , Some ( "UTC" . to_string ( ) ) ) . into ( ) ) ,
547+ ) ;
548+ let dtype = DType :: Extension ( Arc :: new ( ext_dtype) ) ;
549+
550+ assert_eq ! (
551+ LogicalType :: try_from( & dtype) . unwrap( ) . as_type_id( ) ,
552+ cpp:: DUCKDB_TYPE :: DUCKDB_TYPE_TIMESTAMP_TZ
553+ ) ;
554+ }
555+
529556 #[ test]
530557 fn test_temporal_extension_invalid_time_units ( ) {
531558 use std:: sync:: Arc ;
@@ -552,23 +579,6 @@ mod tests {
552579 assert ! ( LogicalType :: try_from( & dtype) . is_err( ) ) ;
553580 }
554581
555- #[ test]
556- fn test_timestamp_with_timezone_unsupported ( ) {
557- use std:: sync:: Arc ;
558-
559- use vortex:: dtype:: datetime:: { TIMESTAMP_ID , TemporalMetadata , TimeUnit } ;
560- use vortex:: dtype:: { ExtDType , PType } ;
561-
562- let ext_dtype = ExtDType :: new (
563- TIMESTAMP_ID . clone ( ) ,
564- Arc :: new ( DType :: Primitive ( PType :: I64 , Nullability :: NonNullable ) ) ,
565- Some ( TemporalMetadata :: Timestamp ( TimeUnit :: Us , Some ( "UTC" . to_string ( ) ) ) . into ( ) ) ,
566- ) ;
567- let dtype = DType :: Extension ( Arc :: new ( ext_dtype) ) ;
568-
569- assert ! ( LogicalType :: try_from( & dtype) . is_err( ) ) ;
570- }
571-
572582 #[ test]
573583 fn test_unsupported_extension_type ( ) {
574584 use vortex:: dtype:: { ExtDType , ExtID , PType } ;
0 commit comments