Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitafef88e

Browse files
committed
Add jiff tests and overflow checks
This adds tests in the same fashion as the existing ones for `chrono`and `time`.Overflow is now handled using fallible operations.For example, `Span:microseconds` is replaced with `Span::try_microseconds`.Postgres infinity values are workiing as expected.All tests are passing.
1 parentc96342d commitafef88e

File tree

3 files changed

+231
-17
lines changed

3 files changed

+231
-17
lines changed

‎postgres-types/src/jiff_01.rs‎

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,40 @@ fn round_us<'a>() -> SpanRound<'a> {
2323
SpanRound::new().largest(Unit::Microsecond)
2424
}
2525

26+
fndecode_err<E>(_e:E) ->Box<dynError +Sync +Send>
27+
where
28+
E:Error,
29+
{
30+
"value too large to decode".into()
31+
}
32+
33+
fntransmit_err<E>(_e:E) ->Box<dynError +Sync +Send>
34+
where
35+
E:Error,
36+
{
37+
"value too large to transmit".into()
38+
}
39+
2640
impl<'a>FromSql<'a>forDateTime{
2741
fnfrom_sql(_:&Type,raw:&[u8]) ->Result<DateTime,Box<dynError +Sync +Send>>{
28-
let t = types::timestamp_from_sql(raw)?;
29-
Ok(base().checked_add(Span::new().microseconds(t))?)
42+
let v = types::timestamp_from_sql(raw)?;
43+
Span::new()
44+
.try_microseconds(v)
45+
.and_then(|s|base().checked_add(s))
46+
.map_err(decode_err)
3047
}
3148

3249
accepts!(TIMESTAMP);
3350
}
3451

3552
implToSqlforDateTime{
3653
fnto_sql(&self, _:&Type,w:&mutBytesMut) ->Result<IsNull,Box<dynError +Sync +Send>>{
37-
let span =self.since(base())?.round(round_us())?;
38-
types::timestamp_to_sql(span.get_microseconds(), w);
54+
let v =self
55+
.since(base())
56+
.and_then(|s| s.round(round_us()))
57+
.map_err(transmit_err)?
58+
.get_microseconds();
59+
types::timestamp_to_sql(v, w);
3960
Ok(IsNull::No)
4061
}
4162

@@ -45,17 +66,24 @@ impl ToSql for DateTime {
4566

4667
impl<'a>FromSql<'a>forTimestamp{
4768
fnfrom_sql(_:&Type,raw:&[u8]) ->Result<Timestamp,Box<dynError +Sync +Send>>{
48-
let t = types::timestamp_from_sql(raw)?;
49-
Ok(base_ts().checked_add(Span::new().microseconds(t))?)
69+
let v = types::timestamp_from_sql(raw)?;
70+
Span::new()
71+
.try_microseconds(v)
72+
.and_then(|s|base_ts().checked_add(s))
73+
.map_err(decode_err)
5074
}
5175

5276
accepts!(TIMESTAMPTZ);
5377
}
5478

5579
implToSqlforTimestamp{
5680
fnto_sql(&self, _:&Type,w:&mutBytesMut) ->Result<IsNull,Box<dynError +Sync +Send>>{
57-
let span =self.since(base_ts())?.round(round_us())?;
58-
types::timestamp_to_sql(span.get_microseconds(), w);
81+
let v =self
82+
.since(base_ts())
83+
.and_then(|s| s.round(round_us()))
84+
.map_err(transmit_err)?
85+
.get_microseconds();
86+
types::timestamp_to_sql(v, w);
5987
Ok(IsNull::No)
6088
}
6189

@@ -65,17 +93,19 @@ impl ToSql for Timestamp {
6593

6694
impl<'a>FromSql<'a>forDate{
6795
fnfrom_sql(_:&Type,raw:&[u8]) ->Result<Date,Box<dynError +Sync +Send>>{
68-
let jd = types::date_from_sql(raw)?;
69-
Ok(base().date().checked_add(Span::new().days(jd))?)
96+
let v = types::date_from_sql(raw)?;
97+
Span::new()
98+
.try_days(v)
99+
.and_then(|s|base().date().checked_add(s))
100+
.map_err(decode_err)
70101
}
71-
72102
accepts!(DATE);
73103
}
74104

75105
implToSqlforDate{
76106
fnto_sql(&self, _:&Type,w:&mutBytesMut) ->Result<IsNull,Box<dynError +Sync +Send>>{
77-
letjd =self.since(base().date())?.get_days();
78-
types::date_to_sql(jd, w);
107+
letv =self.since(base().date()).map_err(transmit_err)?.get_days();
108+
types::date_to_sql(v, w);
79109
Ok(IsNull::No)
80110
}
81111

@@ -85,17 +115,24 @@ impl ToSql for Date {
85115

86116
impl<'a>FromSql<'a>forTime{
87117
fnfrom_sql(_:&Type,raw:&[u8]) ->Result<Time,Box<dynError +Sync +Send>>{
88-
let usec = types::time_from_sql(raw)?;
89-
Ok(Time::midnight() +Span::new().microseconds(usec))
118+
let v = types::time_from_sql(raw)?;
119+
Span::new()
120+
.try_microseconds(v)
121+
.and_then(|s|Time::midnight().checked_add(s))
122+
.map_err(decode_err)
90123
}
91124

92125
accepts!(TIME);
93126
}
94127

95128
implToSqlforTime{
96129
fnto_sql(&self, _:&Type,w:&mutBytesMut) ->Result<IsNull,Box<dynError +Sync +Send>>{
97-
let span =self.since(Time::midnight())?.round(round_us())?;
98-
types::time_to_sql(span.get_microseconds(), w);
130+
let v =self
131+
.since(Time::midnight())
132+
.and_then(|s| s.round(round_us()))
133+
.map_err(transmit_err)?
134+
.get_microseconds();
135+
types::time_to_sql(v, w);
99136
Ok(IsNull::No)
100137
}
101138

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
use jiff_01::{
2+
civil::{DateasJiffDate,DateTime,Time},
3+
TimestampasJiffTimestamp,
4+
};
5+
use std::fmt;
6+
use tokio_postgres::{
7+
types::{Date,FromSqlOwned,Timestamp},
8+
Client,
9+
};
10+
11+
usecrate::connect;
12+
usecrate::types::test_type;
13+
14+
#[tokio::test]
15+
asyncfntest_datetime_params(){
16+
fnmake_check(s:&str) ->(Option<DateTime>,&str){
17+
(Some(s.trim_matches('\'').parse().unwrap()), s)
18+
}
19+
test_type(
20+
"TIMESTAMP",
21+
&[
22+
make_check("'1970-01-01 00:00:00.010000000'"),
23+
make_check("'1965-09-25 11:19:33.100314000'"),
24+
make_check("'2010-02-09 23:11:45.120200000'"),
25+
(None,"NULL"),
26+
],
27+
)
28+
.await;
29+
}
30+
31+
#[tokio::test]
32+
asyncfntest_with_special_datetime_params(){
33+
fnmake_check(s:&str) ->(Timestamp<DateTime>,&str){
34+
(Timestamp::Value(s.trim_matches('\'').parse().unwrap()), s)
35+
}
36+
test_type(
37+
"TIMESTAMP",
38+
&[
39+
make_check("'1970-01-01 00:00:00.010000000'"),
40+
make_check("'1965-09-25 11:19:33.100314000'"),
41+
make_check("'2010-02-09 23:11:45.120200000'"),
42+
(Timestamp::PosInfinity,"'infinity'"),
43+
(Timestamp::NegInfinity,"'-infinity'"),
44+
],
45+
)
46+
.await;
47+
}
48+
49+
#[tokio::test]
50+
asyncfntest_timestamp_params(){
51+
fnmake_check(s:&str) ->(Option<JiffTimestamp>,&str){
52+
(Some(s.trim_matches('\'').parse().unwrap()), s)
53+
}
54+
test_type(
55+
"TIMESTAMP WITH TIME ZONE",
56+
&[
57+
make_check("'1970-01-01 00:00:00.010000000Z'"),
58+
make_check("'1965-09-25 11:19:33.100314000Z'"),
59+
make_check("'2010-02-09 23:11:45.120200000Z'"),
60+
(None,"NULL"),
61+
],
62+
)
63+
.await;
64+
}
65+
66+
#[tokio::test]
67+
asyncfntest_with_special_timestamp_params(){
68+
fnmake_check(s:&str) ->(Timestamp<JiffTimestamp>,&str){
69+
(Timestamp::Value(s.trim_matches('\'').parse().unwrap()), s)
70+
}
71+
test_type(
72+
"TIMESTAMP WITH TIME ZONE",
73+
&[
74+
make_check("'1970-01-01 00:00:00.010000000Z'"),
75+
make_check("'1965-09-25 11:19:33.100314000Z'"),
76+
make_check("'2010-02-09 23:11:45.120200000Z'"),
77+
(Timestamp::PosInfinity,"'infinity'"),
78+
(Timestamp::NegInfinity,"'-infinity'"),
79+
],
80+
)
81+
.await;
82+
}
83+
84+
#[tokio::test]
85+
asyncfntest_date_params(){
86+
fnmake_check(s:&str) ->(Option<JiffDate>,&str){
87+
(Some(s.trim_matches('\'').parse().unwrap()), s)
88+
}
89+
test_type(
90+
"DATE",
91+
&[
92+
make_check("'1970-01-01'"),
93+
make_check("'1965-09-25'"),
94+
make_check("'2010-02-09'"),
95+
(None,"NULL"),
96+
],
97+
)
98+
.await;
99+
}
100+
101+
#[tokio::test]
102+
asyncfntest_with_special_date_params(){
103+
fnmake_check(s:&str) ->(Date<JiffDate>,&str){
104+
(Date::Value(s.trim_matches('\'').parse().unwrap()), s)
105+
}
106+
test_type(
107+
"DATE",
108+
&[
109+
make_check("'1970-01-01'"),
110+
make_check("'1965-09-25'"),
111+
make_check("'2010-02-09'"),
112+
(Date::PosInfinity,"'infinity'"),
113+
(Date::NegInfinity,"'-infinity'"),
114+
],
115+
)
116+
.await;
117+
}
118+
119+
#[tokio::test]
120+
asyncfntest_time_params(){
121+
fnmake_check(s:&str) ->(Option<Time>,&str){
122+
(Some(s.trim_matches('\'').parse().unwrap()), s)
123+
}
124+
test_type(
125+
"TIME",
126+
&[
127+
make_check("'00:00:00.010000000'"),
128+
make_check("'11:19:33.100314000'"),
129+
make_check("'23:11:45.120200000'"),
130+
(None,"NULL"),
131+
],
132+
)
133+
.await;
134+
}
135+
136+
#[tokio::test]
137+
asyncfntest_special_params_without_wrapper(){
138+
asyncfnassert_overflows<T>(client:&mutClient,val:&str,sql_type:&str)
139+
where
140+
T:FromSqlOwned + fmt::Debug,
141+
{
142+
let err = client
143+
.query_one(&*format!("SELECT {}::{}", val, sql_type),&[])
144+
.await
145+
.unwrap()
146+
.try_get::<_,T>(0)
147+
.unwrap_err();
148+
149+
assert_eq!(
150+
err.to_string(),
151+
"error deserializing column 0: value too large to decode"
152+
);
153+
154+
let err = client
155+
.query_one(&*format!("SELECT {}::{}", val, sql_type),&[])
156+
.await
157+
.unwrap()
158+
.try_get::<_,T>(0)
159+
.unwrap_err();
160+
161+
assert_eq!(
162+
err.to_string(),
163+
"error deserializing column 0: value too large to decode"
164+
);
165+
}
166+
167+
letmut client =connect("user=postgres").await;
168+
169+
assert_overflows::<DateTime>(&mut client,"'-infinity'","timestamp").await;
170+
assert_overflows::<DateTime>(&mut client,"'infinity'","timestamp").await;
171+
assert_overflows::<JiffTimestamp>(&mut client,"'-infinity'","timestamptz").await;
172+
assert_overflows::<JiffTimestamp>(&mut client,"'infinity'","timestamptz").await;
173+
assert_overflows::<JiffDate>(&mut client,"'-infinity'","date").await;
174+
assert_overflows::<JiffDate>(&mut client,"'infinity'","date").await;
175+
}

‎tokio-postgres/tests/test/types/mod.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ mod eui48_1;
2323
mod geo_types_06;
2424
#[cfg(feature ="with-geo-types-0_7")]
2525
mod geo_types_07;
26+
#[cfg(feature ="with-jiff-0_1")]
27+
mod jiff_01;
2628
#[cfg(feature ="with-serde_json-1")]
2729
mod serde_json_1;
2830
#[cfg(feature ="with-smol_str-01")]

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp