@@ -187,22 +187,25 @@ fn convert_data_type(pg_type: &Type) -> DbDataType {
187187 Type :: INT4 => DbDataType :: Int32 ,
188188 Type :: INT8 => DbDataType :: Int64 ,
189189 Type :: TEXT | Type :: VARCHAR | Type :: BPCHAR => DbDataType :: Str ,
190+ Type :: TIMESTAMP | Type :: TIMESTAMPTZ => DbDataType :: Timestamp ,
191+ Type :: DATE => DbDataType :: Date ,
192+ Type :: TIME => DbDataType :: Time ,
190193 _ => {
191194 tracing:: debug!( "Couldn't convert Postgres type {} to WIT" , pg_type. name( ) , ) ;
192195 DbDataType :: Other
193196 }
194197 }
195198}
196199
197- fn convert_row ( row : & Row ) -> Result < Vec < DbValue > , tokio_postgres :: Error > {
200+ fn convert_row ( row : & Row ) -> anyhow :: Result < Vec < DbValue > > {
198201 let mut result = Vec :: with_capacity ( row. len ( ) ) ;
199202 for index in 0 ..row. len ( ) {
200203 result. push ( convert_entry ( row, index) ?) ;
201204 }
202205 Ok ( result)
203206}
204207
205- fn convert_entry ( row : & Row , index : usize ) -> Result < DbValue , tokio_postgres :: Error > {
208+ fn convert_entry ( row : & Row , index : usize ) -> anyhow :: Result < DbValue > {
206209 let column = & row. columns ( ) [ index] ;
207210 let value = match column. type_ ( ) {
208211 & Type :: BOOL => {
@@ -261,6 +264,27 @@ fn convert_entry(row: &Row, index: usize) -> Result<DbValue, tokio_postgres::Err
261264 None => DbValue :: DbNull ,
262265 }
263266 }
267+ & Type :: TIMESTAMP | & Type :: TIMESTAMPTZ => {
268+ let value: Option < chrono:: NaiveDateTime > = row. try_get ( index) ?;
269+ match value {
270+ Some ( v) => DbValue :: Datetime ( tuplify_date_time ( v) ?) ,
271+ None => DbValue :: DbNull ,
272+ }
273+ }
274+ & Type :: DATE => {
275+ let value: Option < chrono:: NaiveDate > = row. try_get ( index) ?;
276+ match value {
277+ Some ( v) => DbValue :: Date ( tuplify_date ( v) ?) ,
278+ None => DbValue :: DbNull ,
279+ }
280+ }
281+ & Type :: TIME => {
282+ let value: Option < chrono:: NaiveTime > = row. try_get ( index) ?;
283+ match value {
284+ Some ( v) => DbValue :: Time ( tuplify_time ( v) ?) ,
285+ None => DbValue :: DbNull ,
286+ }
287+ }
264288 t => {
265289 tracing:: debug!(
266290 "Couldn't convert Postgres type {} in column {}" ,
@@ -273,6 +297,41 @@ fn convert_entry(row: &Row, index: usize) -> Result<DbValue, tokio_postgres::Err
273297 Ok ( value)
274298}
275299
300+ // Functions to convert from the chrono types to the WIT interface tuples
301+ fn tuplify_date_time (
302+ value : chrono:: NaiveDateTime ,
303+ ) -> anyhow:: Result < ( i32 , u8 , u8 , u8 , u8 , u8 , u32 ) > {
304+ use chrono:: { Datelike , Timelike } ;
305+ Ok ( (
306+ value. year ( ) ,
307+ value. month ( ) . try_into ( ) ?,
308+ value. day ( ) . try_into ( ) ?,
309+ value. hour ( ) . try_into ( ) ?,
310+ value. minute ( ) . try_into ( ) ?,
311+ value. second ( ) . try_into ( ) ?,
312+ value. nanosecond ( ) ,
313+ ) )
314+ }
315+
316+ fn tuplify_date ( value : chrono:: NaiveDate ) -> anyhow:: Result < ( i32 , u8 , u8 ) > {
317+ use chrono:: Datelike ;
318+ Ok ( (
319+ value. year ( ) ,
320+ value. month ( ) . try_into ( ) ?,
321+ value. day ( ) . try_into ( ) ?,
322+ ) )
323+ }
324+
325+ fn tuplify_time ( value : chrono:: NaiveTime ) -> anyhow:: Result < ( u8 , u8 , u8 , u32 ) > {
326+ use chrono:: Timelike ;
327+ Ok ( (
328+ value. hour ( ) . try_into ( ) ?,
329+ value. minute ( ) . try_into ( ) ?,
330+ value. second ( ) . try_into ( ) ?,
331+ value. nanosecond ( ) ,
332+ ) )
333+ }
334+
276335/// Although the Postgres crate converts Rust Option::None to Postgres NULL,
277336/// it enforces the type of the Option as it does so. (For example, trying to
278337/// pass an Option::<i32>::None to a VARCHAR column fails conversion.) As we
0 commit comments