@@ -4,10 +4,7 @@ use crate::{protocol::Format, ProtocolError};
44use bytes:: { BufMut , BytesMut } ;
55#[ cfg( feature = "with-chrono" ) ]
66use chrono:: { NaiveDate , NaiveDateTime } ;
7- use std:: {
8- fmt:: { Display , Formatter } ,
9- io:: { Error , ErrorKind } ,
10- } ;
7+ use std:: io:: { Error , ErrorKind } ;
118
129/// This trait explains how to encode values to the protocol format
1310pub trait ToProtocolValue : std:: fmt:: Debug {
@@ -149,145 +146,6 @@ impl ToProtocolValue for NaiveDate {
149146 }
150147}
151148
152- #[ derive( Debug , Clone , Default ) ]
153- pub struct IntervalValue {
154- pub months : i32 ,
155- pub days : i32 ,
156- pub hours : i32 ,
157- pub mins : i32 ,
158- pub secs : i32 ,
159- pub usecs : i32 ,
160- }
161-
162- impl IntervalValue {
163- pub fn new ( months : i32 , days : i32 , hours : i32 , mins : i32 , secs : i32 , usecs : i32 ) -> Self {
164- Self {
165- months,
166- days,
167- hours,
168- mins,
169- secs,
170- usecs,
171- }
172- }
173-
174- pub fn is_zeroed ( & self ) -> bool {
175- self . months == 0
176- && self . days == 0
177- && self . hours == 0
178- && self . mins == 0
179- && self . secs == 0
180- && self . usecs == 0
181- }
182-
183- pub fn extract_years_month ( & self ) -> ( i32 , i32 ) {
184- let years = ( self . months as f64 / 12_f64 ) . floor ( ) ;
185- let month = self . months as f64 - ( years * 12_f64 ) ;
186-
187- ( years as i32 , month as i32 )
188- }
189-
190- pub fn as_iso_str ( & self ) -> String {
191- if self . is_zeroed ( ) {
192- return "00:00:00" . to_owned ( ) ;
193- }
194-
195- let mut res = "" . to_owned ( ) ;
196- let ( years, months) = self . extract_years_month ( ) ;
197-
198- if years != 0 {
199- if years == 1 {
200- res. push_str ( & format ! ( "{:#?} year " , years) )
201- } else {
202- res. push_str ( & format ! ( "{:#?} years " , years) )
203- }
204- }
205-
206- if months != 0 {
207- if months == 1 {
208- res. push_str ( & format ! ( "{:#?} mon " , months) ) ;
209- } else {
210- res. push_str ( & format ! ( "{:#?} mons " , months) ) ;
211- }
212- }
213-
214- if self . hours != 0 || self . mins != 0 || self . secs != 0 || self . usecs != 0 {
215- if self . hours < 0 || self . mins < 0 || self . secs < 0 || self . usecs < 0 {
216- res. push ( '-' )
217- } ;
218-
219- res. push_str ( & format ! (
220- "{:02}:{:02}:{:02}" ,
221- self . hours. abs( ) ,
222- self . mins. abs( ) ,
223- self . secs. abs( )
224- ) ) ;
225-
226- if self . usecs != 0 {
227- res. push_str ( & format ! ( ".{:06}" , self . usecs. abs( ) ) )
228- }
229- }
230-
231- res. trim ( ) . to_string ( )
232- }
233-
234- pub fn as_postgresql_str ( & self ) -> String {
235- let ( years, months) = self . extract_years_month ( ) ;
236-
237- // We manually format sign for the case where self.secs == 0, self.usecs < 0.
238- // We follow assumptions about consistency of hours/mins/secs/usecs signs as in
239- // as_iso_str here.
240- format ! (
241- "{} years {} mons {} days {} hours {} mins {}{}.{} secs" ,
242- years,
243- months,
244- self . days,
245- self . hours,
246- self . mins,
247- if self . secs < 0 || self . usecs < 0 {
248- "-"
249- } else {
250- ""
251- } ,
252- self . secs. abs( ) ,
253- if self . usecs == 0 {
254- "00" . to_string( )
255- } else {
256- format!( "{:06}" , self . usecs. abs( ) )
257- }
258- )
259- }
260- }
261-
262- impl Display for IntervalValue {
263- fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
264- // TODO lift formatter higher, to as_postgresql_str
265- // https://github.com/postgres/postgres/blob/REL_14_4/src/interfaces/ecpg/pgtypeslib/interval.c#L763
266- f. write_str ( & self . as_postgresql_str ( ) )
267- }
268- }
269-
270- impl ToProtocolValue for IntervalValue {
271- // https://github.com/postgres/postgres/blob/REL_14_4/src/backend/utils/adt/timestamp.c#L958
272- fn to_text ( & self , buf : & mut BytesMut ) -> Result < ( ) , ProtocolError > {
273- self . to_string ( ) . to_text ( buf)
274- }
275-
276- // https://github.com/postgres/postgres/blob/REL_14_4/src/backend/utils/adt/timestamp.c#L1005
277- fn to_binary ( & self , buf : & mut BytesMut ) -> Result < ( ) , ProtocolError > {
278- let usecs = self . hours as i64 * 60 * 60 * 1_000_000
279- + self . mins as i64 * 60 * 1_000_000
280- + self . secs as i64 * 1_000_000
281- + self . usecs as i64 ;
282-
283- buf. put_i32 ( 16 ) ;
284- buf. put_i64 ( usecs) ;
285- buf. put_i32 ( self . days ) ;
286- buf. put_i32 ( self . months ) ;
287-
288- Ok ( ( ) )
289- }
290- }
291149
292150#[ cfg( test) ]
293151mod tests {
@@ -325,59 +183,4 @@ mod tests {
325183 Ok ( ( ) )
326184 }
327185
328- #[ test]
329- fn test_interval_to_iso ( ) -> Result < ( ) , ProtocolError > {
330- assert_eq ! (
331- IntervalValue :: new( 1 , 0 , 0 , 0 , 0 , 0 ) . as_iso_str( ) ,
332- "1 mon" . to_string( )
333- ) ;
334- assert_eq ! (
335- IntervalValue :: new( 14 , 0 , 0 , 0 , 0 , 0 ) . as_iso_str( ) ,
336- "1 year 2 mons" . to_string( )
337- ) ;
338- assert_eq ! (
339- IntervalValue :: new( 0 , 1 , 1 , 1 , 1 , 1 ) . as_iso_str( ) ,
340- "01:01:01.000001" . to_string( )
341- ) ;
342- assert_eq ! (
343- IntervalValue :: new( 0 , 0 , -1 , 1 , 1 , 1 ) . as_iso_str( ) ,
344- "-01:01:01.000001" . to_string( )
345- ) ;
346- assert_eq ! (
347- IntervalValue :: new( 0 , 0 , 0 , 0 , 0 , 0 ) . as_iso_str( ) ,
348- "00:00:00" . to_string( )
349- ) ;
350-
351- Ok ( ( ) )
352- }
353-
354- #[ test]
355- fn test_interval_to_postgres ( ) -> Result < ( ) , ProtocolError > {
356- assert_eq ! (
357- IntervalValue :: new( 0 , 0 , 0 , 0 , 0 , 0 ) . to_string( ) ,
358- "0 years 0 mons 0 days 0 hours 0 mins 0.00 secs" . to_string( )
359- ) ;
360-
361- assert_eq ! (
362- IntervalValue :: new( 0 , 0 , 0 , 0 , 1 , 23 ) . to_string( ) ,
363- "0 years 0 mons 0 days 0 hours 0 mins 1.000023 secs" . to_string( )
364- ) ;
365-
366- assert_eq ! (
367- IntervalValue :: new( 0 , 0 , 0 , 0 , -1 , -23 ) . to_string( ) ,
368- "0 years 0 mons 0 days 0 hours 0 mins -1.000023 secs" . to_string( )
369- ) ;
370-
371- assert_eq ! (
372- IntervalValue :: new( 0 , 0 , 0 , 0 , -1 , 0 ) . to_string( ) ,
373- "0 years 0 mons 0 days 0 hours 0 mins -1.00 secs" . to_string( )
374- ) ;
375-
376- assert_eq ! (
377- IntervalValue :: new( 0 , 0 , -14 , -5 , -1 , 0 ) . to_string( ) ,
378- "0 years 0 mons 0 days -14 hours -5 mins -1.00 secs" . to_string( )
379- ) ;
380-
381- Ok ( ( ) )
382- }
383186}
0 commit comments