Skip to content

Commit 96c677c

Browse files
remote date time wrappers
Signed-off-by: Michelle Dhanani <[email protected]> Co-authored-by: Brian Hardock <[email protected]>
1 parent 38f006d commit 96c677c

File tree

4 files changed

+71
-54
lines changed

4 files changed

+71
-54
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/postgres-v3/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ anyhow = "1"
1313
http = "1.0.0"
1414
# The Spin SDK.
1515
spin-sdk = { path = "../.." }
16-
16+
# For handling date/time types
17+
chrono = "0.4.38"

examples/postgres-v3/src/lib.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
#![allow(dead_code)]
22
use anyhow::Result;
33
use http::{Request, Response};
4-
use spin_sdk::{
5-
http_component, pg3,
6-
pg3::{Date, Decode},
7-
};
4+
use spin_sdk::{http_component, pg3, pg3::Decode};
85

96
// The environment variable set in `spin.toml` that points to the
107
// address of the Pg server that the component will write to
@@ -16,7 +13,7 @@ struct Article {
1613
title: String,
1714
content: String,
1815
authorname: String,
19-
published: Date,
16+
published: chrono::NaiveDate,
2017
coauthor: Option<String>,
2118
}
2219

@@ -28,7 +25,7 @@ impl TryFrom<&pg3::Row> for Article {
2825
let title = String::decode(&row[1])?;
2926
let content = String::decode(&row[2])?;
3027
let authorname = String::decode(&row[3])?;
31-
let published = Date::decode(&row[4])?;
28+
let published = chrono::NaiveDate::decode(&row[4])?;
3229
let coauthor = Option::<String>::decode(&row[5])?;
3330

3431
Ok(Self {

src/pg3.rs

Lines changed: 65 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@
22
//!
33
//! # Types
44
//!
5-
//! | Rust type | WIT (db-value) | Postgres type(s) |
6-
//! |------------|-----------------------------------------------|----------------------------- |
7-
//! | `bool` | boolean(bool) | BOOL |
8-
//! | `i16` | int16(s16) | SMALLINT, SMALLSERIAL, INT2 |
9-
//! | `i32` | int32(s32) | INT, SERIAL, INT4 |
10-
//! | `i64` | int64(s64) | BIGINT, BIGSERIAL, INT8 |
11-
//! | `f32` | floating32(float32) | REAL, FLOAT4 |
12-
//! | `f64` | floating64(float64) | DOUBLE PRECISION, FLOAT8 |
13-
//! | `String` | str(string) | VARCHAR, CHAR(N), TEXT |
14-
//! | `Vec<u8>` | binary(list\<u8\>) | BYTEA |
15-
//! | `Date` | date(tuple<s32, u8, u8>) | DATE |
16-
//! | `Time` | time(tuple<u8, u8, u8, u32>) | TIME |
17-
//! | `Datetime` | datetime(tuple<s32, u8, u8, u8, u8, u8, u32>) | TIMESTAMP |
18-
//! | `Timestamp`| timestamp(s64) | BIGINT |
5+
//! | Rust type | WIT (db-value) | Postgres type(s) |
6+
//! |-------------------------|-----------------------------------------------|----------------------------- |
7+
//! | `bool` | boolean(bool) | BOOL |
8+
//! | `i16` | int16(s16) | SMALLINT, SMALLSERIAL, INT2 |
9+
//! | `i32` | int32(s32) | INT, SERIAL, INT4 |
10+
//! | `i64` | int64(s64) | BIGINT, BIGSERIAL, INT8 |
11+
//! | `f32` | floating32(float32) | REAL, FLOAT4 |
12+
//! | `f64` | floating64(float64) | DOUBLE PRECISION, FLOAT8 |
13+
//! | `String` | str(string) | VARCHAR, CHAR(N), TEXT |
14+
//! | `Vec<u8>` | binary(list\<u8\>) | BYTEA |
15+
//! | `chrono::NaiveDate` | date(tuple<s32, u8, u8>) | DATE |
16+
//! | `chrono::NaiveTime` | time(tuple<u8, u8, u8, u32>) | TIME |
17+
//! | `chrono::NaiveDateTime` | datetime(tuple<s32, u8, u8, u8, u8, u8, u32>) | TIMESTAMP |
18+
//! | `chrono::Duration` | timestamp(s64) | BIGINT |
1919
2020
#[doc(inline)]
2121
pub use super::wit::pg3::{Error as PgError, *};
@@ -124,11 +124,7 @@ impl Decode for String {
124124
}
125125
}
126126

127-
/// Native representation of the WIT postgres Date value.
128-
#[derive(Clone, Debug, PartialEq)]
129-
pub struct Date(pub chrono::NaiveDate);
130-
131-
impl Decode for Date {
127+
impl Decode for chrono::NaiveDate {
132128
fn decode(value: &DbValue) -> Result<Self, Error> {
133129
match value {
134130
DbValue::Date((year, month, day)) => {
@@ -140,18 +136,14 @@ impl Decode for Date {
140136
year, month, day
141137
))
142138
})?;
143-
Ok(Date(naive_date))
139+
Ok(naive_date)
144140
}
145141
_ => Err(Error::Decode(format_decode_err("DATE", value))),
146142
}
147143
}
148144
}
149145

150-
/// Native representation of the WIT postgres Time value.
151-
#[derive(Clone, Debug, PartialEq)]
152-
pub struct Time(pub chrono::NaiveTime);
153-
154-
impl Decode for Time {
146+
impl Decode for chrono::NaiveTime {
155147
fn decode(value: &DbValue) -> Result<Self, Error> {
156148
match value {
157149
DbValue::Time((hour, minute, second, nanosecond)) => {
@@ -167,18 +159,14 @@ impl Decode for Time {
167159
hour, minute, second, nanosecond
168160
))
169161
})?;
170-
Ok(Time(naive_time))
162+
Ok(naive_time)
171163
}
172164
_ => Err(Error::Decode(format_decode_err("TIME", value))),
173165
}
174166
}
175167
}
176168

177-
/// Native representation of the WIT postgres DateTime value.
178-
#[derive(Clone, Debug, PartialEq)]
179-
pub struct DateTime(pub chrono::NaiveDateTime);
180-
181-
impl Decode for DateTime {
169+
impl Decode for chrono::NaiveDateTime {
182170
fn decode(value: &DbValue) -> Result<Self, Error> {
183171
match value {
184172
DbValue::Datetime((year, month, day, hour, minute, second, nanosecond)) => {
@@ -203,19 +191,30 @@ impl Decode for DateTime {
203191
))
204192
})?;
205193
let dt = chrono::NaiveDateTime::new(naive_date, naive_time);
206-
Ok(DateTime(dt))
194+
Ok(dt)
207195
}
208196
_ => Err(Error::Decode(format_decode_err("DATETIME", value))),
209197
}
210198
}
211199
}
212200

201+
impl Decode for chrono::Duration {
202+
fn decode(value: &DbValue) -> Result<Self, Error> {
203+
match value {
204+
DbValue::Timestamp(n) => Ok(chrono::Duration::seconds(*n)),
205+
_ => Err(Error::Decode(format_decode_err("BIGINT", value))),
206+
}
207+
}
208+
}
209+
213210
fn format_decode_err(types: &str, value: &DbValue) -> String {
214211
format!("Expected {} from the DB but got {:?}", types, value)
215212
}
216213

217214
#[cfg(test)]
218215
mod tests {
216+
use chrono::NaiveDateTime;
217+
219218
use super::*;
220219

221220
#[test]
@@ -285,44 +284,63 @@ mod tests {
285284
#[test]
286285
fn date() {
287286
assert_eq!(
288-
Date::decode(&DbValue::Date((1, 2, 4))).unwrap(),
289-
Date(chrono::NaiveDate::from_ymd_opt(1, 2, 4).unwrap())
287+
chrono::NaiveDate::decode(&DbValue::Date((1, 2, 4))).unwrap(),
288+
chrono::NaiveDate::from_ymd_opt(1, 2, 4).unwrap()
290289
);
291290
assert_ne!(
292-
Date::decode(&DbValue::Date((1, 2, 4))).unwrap(),
293-
Date(chrono::NaiveDate::from_ymd_opt(1, 2, 5).unwrap())
291+
chrono::NaiveDate::decode(&DbValue::Date((1, 2, 4))).unwrap(),
292+
chrono::NaiveDate::from_ymd_opt(1, 2, 5).unwrap()
294293
);
295-
assert!(Option::<Date>::decode(&DbValue::DbNull).unwrap().is_none());
294+
assert!(Option::<chrono::NaiveDate>::decode(&DbValue::DbNull)
295+
.unwrap()
296+
.is_none());
296297
}
297298

298299
#[test]
299300
fn time() {
300301
assert_eq!(
301-
Time::decode(&DbValue::Time((1, 2, 3, 4))).unwrap(),
302-
Time(chrono::NaiveTime::from_hms_nano_opt(1, 2, 3, 4).unwrap())
302+
chrono::NaiveTime::decode(&DbValue::Time((1, 2, 3, 4))).unwrap(),
303+
chrono::NaiveTime::from_hms_nano_opt(1, 2, 3, 4).unwrap()
303304
);
304305
assert_ne!(
305-
Time::decode(&DbValue::Time((1, 2, 3, 4))).unwrap(),
306-
Time(chrono::NaiveTime::from_hms_nano_opt(1, 2, 4, 5).unwrap())
306+
chrono::NaiveTime::decode(&DbValue::Time((1, 2, 3, 4))).unwrap(),
307+
chrono::NaiveTime::from_hms_nano_opt(1, 2, 4, 5).unwrap()
307308
);
308-
assert!(Option::<Time>::decode(&DbValue::DbNull).unwrap().is_none());
309+
assert!(Option::<chrono::NaiveTime>::decode(&DbValue::DbNull)
310+
.unwrap()
311+
.is_none());
309312
}
310313

311314
#[test]
312315
fn datetime() {
313316
let date = chrono::NaiveDate::from_ymd_opt(1, 2, 3).unwrap();
314317
let mut time = chrono::NaiveTime::from_hms_nano_opt(4, 5, 6, 7).unwrap();
315318
assert_eq!(
316-
DateTime::decode(&DbValue::Datetime((1, 2, 3, 4, 5, 6, 7))).unwrap(),
317-
DateTime(chrono::NaiveDateTime::new(date, time))
319+
chrono::NaiveDateTime::decode(&DbValue::Datetime((1, 2, 3, 4, 5, 6, 7))).unwrap(),
320+
chrono::NaiveDateTime::new(date, time)
318321
);
319322

320323
time = chrono::NaiveTime::from_hms_nano_opt(4, 5, 6, 8).unwrap();
321324
assert_ne!(
322-
DateTime::decode(&DbValue::Datetime((1, 2, 3, 4, 5, 6, 7))).unwrap(),
323-
DateTime(chrono::NaiveDateTime::new(date, time))
325+
NaiveDateTime::decode(&DbValue::Datetime((1, 2, 3, 4, 5, 6, 7))).unwrap(),
326+
chrono::NaiveDateTime::new(date, time)
327+
);
328+
assert!(Option::<chrono::NaiveDateTime>::decode(&DbValue::DbNull)
329+
.unwrap()
330+
.is_none());
331+
}
332+
333+
#[test]
334+
fn timestamp() {
335+
assert_eq!(
336+
chrono::Duration::decode(&DbValue::Timestamp(1)).unwrap(),
337+
chrono::Duration::seconds(1),
338+
);
339+
assert_ne!(
340+
chrono::Duration::decode(&DbValue::Timestamp(2)).unwrap(),
341+
chrono::Duration::seconds(1)
324342
);
325-
assert!(Option::<DateTime>::decode(&DbValue::DbNull)
343+
assert!(Option::<chrono::Duration>::decode(&DbValue::DbNull)
326344
.unwrap()
327345
.is_none());
328346
}

0 commit comments

Comments
 (0)