Skip to content

Commit a3896ce

Browse files
KeenSsgrif
authored andcommitted
implement arithmetics to timestamptz (diesel-rs#1657)
* implement add and sub to timestamptz * fix typo * create table before testing * allow add and sub to the generated column structs * test against operations on `now` * use timestamptz only on postgres * fix typo * fix typo * fix typo * give up testing now as timestamptz. Leaving it as another issue * apply #[cfg] in the minimal unit * explicitly use timezone * cfg out timestamptz helper function * trim a blank line
1 parent ce988df commit a3896ce

4 files changed

Lines changed: 108 additions & 8 deletions

File tree

diesel/src/macros/ops.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,5 +80,6 @@ macro_rules! __diesel_generate_ops_impls_if_date_time {
8080
($column_name:ident, Time) => { date_time_expr!($column_name); };
8181
($column_name:ident, Date) => { date_time_expr!($column_name); };
8282
($column_name:ident, Timestamp) => { date_time_expr!($column_name); };
83+
($column_name:ident, Timestamptz) => { date_time_expr!($column_name); };
8384
($column_name:ident, $non_date_time_type:ty) => {};
8485
}

diesel/src/pg/types/mod.rs

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
//! PostgreSQL specific types
22
33
mod array;
4-
mod ranges;
54
#[doc(hidden)]
65
pub mod date_and_time;
76
#[doc(hidden)]
87
pub mod floats;
8+
mod integers;
9+
#[cfg(feature = "serde_json")]
10+
mod json;
11+
#[doc(hidden)]
12+
pub mod money;
913
#[cfg(feature = "network-address")]
1014
mod network_address;
11-
mod integers;
1215
mod numeric;
1316
mod primitives;
17+
mod ranges;
1418
mod record;
1519
#[cfg(feature = "uuid")]
1620
mod uuid;
17-
#[cfg(feature = "serde_json")]
18-
mod json;
19-
#[doc(hidden)]
20-
pub mod money;
2121

2222
/// PostgreSQL specific SQL types
2323
///
@@ -488,3 +488,29 @@ pub mod sql_types {
488488
#[postgres(oid = "650", array_oid = "651")]
489489
pub struct Cidr;
490490
}
491+
492+
mod ops {
493+
use super::sql_types::*;
494+
use sql_types::ops::*;
495+
use sql_types::{Interval, Nullable};
496+
497+
impl Add for Timestamptz {
498+
type Rhs = Interval;
499+
type Output = Timestamptz;
500+
}
501+
502+
impl Add for Nullable<Timestamptz> {
503+
type Rhs = Nullable<Interval>;
504+
type Output = Nullable<Timestamptz>;
505+
}
506+
507+
impl Sub for Timestamptz {
508+
type Rhs = Interval;
509+
type Output = Timestamptz;
510+
}
511+
512+
impl Sub for Nullable<Timestamptz> {
513+
type Rhs = Nullable<Interval>;
514+
type Output = Nullable<Timestamptz>;
515+
}
516+
}

diesel_tests/tests/expressions/date_and_time.rs

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,34 @@ table! {
1212
}
1313
}
1414

15+
#[cfg(feature = "postgres")]
16+
table! {
17+
has_timestamptzs {
18+
id -> Integer,
19+
created_at -> Timestamptz,
20+
updated_at -> Timestamptz,
21+
}
22+
}
23+
1524
table! {
1625
has_time {
1726
id -> Integer,
1827
time -> Time,
1928
}
2029
}
2130

31+
#[cfg(feature = "postgres")]
32+
table! {
33+
nullable_date_and_time {
34+
id -> Integer,
35+
timestamp -> Nullable<Timestamp>,
36+
timestamptz -> Nullable<Timestamptz>,
37+
time -> Nullable<Time>,
38+
date -> Nullable<Date>,
39+
}
40+
}
41+
42+
#[cfg(not(feature = "postgres"))]
2243
table! {
2344
nullable_date_and_time {
2445
id -> Integer,
@@ -226,6 +247,30 @@ fn adding_interval_to_timestamp() {
226247
assert_eq!(expected_data, actual_data);
227248
}
228249

250+
#[test]
251+
#[cfg(feature = "postgres")]
252+
fn adding_interval_to_timestamptz() {
253+
use self::has_timestamptzs::dsl::*;
254+
use diesel::dsl::sql;
255+
256+
let connection = connection();
257+
setup_test_table(&connection);
258+
connection
259+
.execute(
260+
"INSERT INTO has_timestamptzs (created_at, updated_at) VALUES
261+
('2015-11-15 06:07:41+0100', '2015-11-15 20:07:41+0100')",
262+
)
263+
.unwrap();
264+
265+
let expected_data = select(sql::<sql_types::Timestamptz>(
266+
"'2015-11-16 06:07:41+0100'::timestamptz",
267+
)).get_result::<PgTimestamp>(&connection);
268+
let actual_data = has_timestamptzs
269+
.select(created_at + 1.day())
270+
.first::<PgTimestamp>(&connection);
271+
assert_eq!(expected_data, actual_data);
272+
}
273+
229274
#[test]
230275
#[cfg(feature = "postgres")]
231276
fn adding_interval_to_nullable_things() {
@@ -236,8 +281,8 @@ fn adding_interval_to_nullable_things() {
236281
setup_test_table(&connection);
237282
connection
238283
.execute(
239-
"INSERT INTO nullable_date_and_time (timestamp, date, time) VALUES
240-
('2017-08-20 18:13:37', '2017-08-20', '18:13:37')",
284+
"INSERT INTO nullable_date_and_time (timestamp, timestamptz, date, time) VALUES
285+
('2017-08-20 18:13:37', '2017-08-20 18:13:37+0100', '2017-08-20', '18:13:37')",
241286
)
242287
.unwrap();
243288

@@ -249,6 +294,14 @@ fn adding_interval_to_nullable_things() {
249294
.first::<Option<PgTimestamp>>(&connection);
250295
assert_eq!(expected_data, actual_data);
251296

297+
let expected_data = select(sql::<Nullable<sql_types::Timestamptz>>(
298+
"'2017-08-21 18:13:37+0100'::timestamptz",
299+
)).get_result::<Option<PgTimestamp>>(&connection);
300+
let actual_data = nullable_date_and_time
301+
.select(timestamptz + 1.day())
302+
.first::<Option<PgTimestamp>>(&connection);
303+
assert_eq!(expected_data, actual_data);
304+
252305
let expected_data = select(sql::<Nullable<sql_types::Timestamp>>(
253306
"'2017-08-21'::timestamp",
254307
)).get_result::<Option<PgTimestamp>>(&connection);
@@ -281,6 +334,19 @@ fn setup_test_table(conn: &TestConnection) {
281334
).execute(conn)
282335
.unwrap();
283336

337+
#[cfg(feature = "postgres")]
338+
create_table(
339+
"has_timestamptzs",
340+
(
341+
integer("id").primary_key().auto_increment(),
342+
timestamptz("created_at").not_null(),
343+
timestamptz("updated_at")
344+
.not_null()
345+
.default("CURRENT_TIMESTAMP"),
346+
),
347+
).execute(conn)
348+
.unwrap();
349+
284350
create_table(
285351
"has_time",
286352
(
@@ -295,6 +361,8 @@ fn setup_test_table(conn: &TestConnection) {
295361
(
296362
integer("id").primary_key().auto_increment(),
297363
timestamp("timestamp"),
364+
#[cfg(feature = "postgres")]
365+
timestamptz("timestamptz"),
298366
time("time"),
299367
date("date"),
300368
),

diesel_tests/tests/schema_dsl/functions.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ pub fn timestamp<'a>(name: &'a str) -> Column<'a, sql_types::VarChar> {
1818
Column::new(name, "TIMESTAMP")
1919
}
2020

21+
#[cfg(feature = "postgres")]
22+
pub fn timestamptz<'a>(name: &'a str) -> Column<'a, sql_types::VarChar> {
23+
Column::new(name, "TIMESTAMPTZ")
24+
}
25+
2126
pub fn time<'a>(name: &'a str) -> Column<'a, sql_types::VarChar> {
2227
Column::new(name, "TIME")
2328
}

0 commit comments

Comments
 (0)