Skip to content

Commit b668f3d

Browse files
committed
chore: Extract interval value to a separate file
1 parent 760640c commit b668f3d

File tree

3 files changed

+210
-198
lines changed

3 files changed

+210
-198
lines changed

rust/cubesql/pg-srv/src/encoding.rs

Lines changed: 1 addition & 198 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@ use crate::{protocol::Format, ProtocolError};
44
use bytes::{BufMut, BytesMut};
55
#[cfg(feature = "with-chrono")]
66
use 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
1310
pub 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)]
293151
mod 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

Comments
 (0)