Skip to content

Commit 692e3ff

Browse files
authored
Merge pull request diesel-rs#2502 from TaKO8Ki/current-date
Add support for CURRENT_DATE
2 parents 96b5c08 + 2778920 commit 692e3ff

3 files changed

Lines changed: 162 additions & 3 deletions

File tree

diesel/src/expression/functions/date_and_time.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,32 @@ impl AsExpression<Nullable<Timestamptz>> for now {
7171
Coerce::new(self)
7272
}
7373
}
74+
75+
/// Represents the SQL `CURRENT_DATE` constant.
76+
#[allow(non_camel_case_types)]
77+
#[derive(Debug, Copy, Clone, QueryId, ValidGrouping)]
78+
pub struct today;
79+
80+
impl Expression for today {
81+
type SqlType = Date;
82+
}
83+
84+
impl<DB: Backend> QueryFragment<DB> for today {
85+
fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
86+
out.push_sql("CURRENT_DATE");
87+
Ok(())
88+
}
89+
}
90+
91+
impl_selectable_expression!(today);
92+
93+
operator_allowed!(today, Add, add);
94+
operator_allowed!(today, Sub, sub);
95+
96+
impl AsExpression<Nullable<Date>> for today {
97+
type Expression = Coerce<today, Nullable<Date>>;
98+
99+
fn as_expression(self) -> Self::Expression {
100+
Coerce::new(self)
101+
}
102+
}

diesel_tests/tests/expressions/date_and_time.rs

Lines changed: 132 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ table! {
2929
}
3030
}
3131

32+
table! {
33+
has_date {
34+
id -> Integer,
35+
date -> Date,
36+
}
37+
}
38+
3239
#[cfg(feature = "postgres")]
3340
table! {
3441
nullable_date_and_time {
@@ -134,6 +141,120 @@ fn now_can_be_used_as_nullable() {
134141
assert_eq!(Ok(Some(true)), result);
135142
}
136143

144+
#[test]
145+
fn today_can_be_used_as_nullable() {
146+
use diesel::sql_types::Date;
147+
148+
let nullable_date = sql::<Nullable<Date>>("CURRENT_DATE");
149+
let result = select(nullable_date.eq(today)).get_result(&connection());
150+
151+
assert_eq!(Ok(Some(true)), result);
152+
}
153+
154+
#[test]
155+
#[cfg(feature = "postgres")]
156+
fn today_executes_sql_function_current_date() {
157+
use self::has_date::dsl::*;
158+
159+
let connection = connection();
160+
setup_test_table(&connection);
161+
connection
162+
.execute(
163+
"INSERT INTO has_date (date) VALUES
164+
(current_date - '1 day'::interval), (current_date + '1 day'::interval);",
165+
)
166+
.unwrap();
167+
168+
let before_today = has_date
169+
.select(id)
170+
.filter(date.lt(today))
171+
.load::<i32>(&connection);
172+
let after_today = has_date
173+
.select(id)
174+
.filter(date.gt(today))
175+
.load::<i32>(&connection);
176+
assert_eq!(Ok(vec![1]), before_today);
177+
assert_eq!(Ok(vec![2]), after_today);
178+
}
179+
180+
#[test]
181+
#[cfg(feature = "sqlite")]
182+
fn today_executes_sql_function_current_date() {
183+
use self::has_date::dsl::*;
184+
185+
let connection = connection();
186+
setup_test_table(&connection);
187+
connection
188+
.execute(
189+
"INSERT INTO has_date (date) VALUES
190+
(DATE('now', '-1 day')), (DATE('now', '+1 day'));",
191+
)
192+
.unwrap();
193+
194+
let before_today = has_date
195+
.select(id)
196+
.filter(date.lt(today))
197+
.load::<i32>(&connection);
198+
let after_today = has_date
199+
.select(id)
200+
.filter(date.gt(today))
201+
.load::<i32>(&connection);
202+
assert_eq!(Ok(vec![1]), before_today);
203+
assert_eq!(Ok(vec![2]), after_today);
204+
}
205+
206+
#[test]
207+
#[cfg(feature = "mysql")]
208+
fn today_executes_sql_function_current_date() {
209+
use self::has_date::dsl::*;
210+
211+
let connection = connection();
212+
setup_test_table(&connection);
213+
connection
214+
.execute(
215+
"INSERT INTO has_date (date) VALUES
216+
(current_date - interval 1 day), (current_date + interval 1 day);",
217+
)
218+
.unwrap();
219+
220+
let before_today = has_date
221+
.select(id)
222+
.filter(date.lt(today))
223+
.load::<i32>(&connection);
224+
let after_today = has_date
225+
.select(id)
226+
.filter(date.gt(today))
227+
.load::<i32>(&connection);
228+
assert_eq!(Ok(vec![1]), before_today);
229+
assert_eq!(Ok(vec![2]), after_today);
230+
}
231+
232+
#[test]
233+
#[cfg(feature = "mysql")]
234+
fn now_executes_sql_function_now() {
235+
use self::has_timestamps::dsl::*;
236+
237+
let connection = connection();
238+
setup_test_table(&connection);
239+
connection
240+
.execute(
241+
"INSERT INTO has_timestamps (created_at) VALUES
242+
(NOW() - interval 1 day), (NOW() + interval 1 day)",
243+
)
244+
.unwrap();
245+
246+
let before_today = has_timestamps
247+
.select(id)
248+
.filter(created_at.lt(now))
249+
.load::<i32>(&connection);
250+
let after_today = has_timestamps
251+
.select(id)
252+
.filter(created_at.gt(now))
253+
.load::<i32>(&connection);
254+
assert_eq!(Ok(vec![1]), before_today);
255+
assert_eq!(Ok(vec![2]), after_today);
256+
}
257+
137258
#[test]
138259
#[cfg(feature = "sqlite")]
139260
fn now_executes_sql_function_now() {
@@ -159,7 +280,6 @@ fn now_executes_sql_function_now() {
159280
assert_eq!(Ok(vec![1]), before_today);
160281
assert_eq!(Ok(vec![2]), after_today);
161282
}
162-
163283
#[test]
164284
#[cfg(not(feature = "mysql"))] // FIXME: Figure out how to handle tests that modify schema
165285
fn date_uses_sql_function_date() {
@@ -333,7 +453,7 @@ fn adding_interval_to_nullable_things() {
333453
assert_eq!(expected_data, actual_data);
334454
}
335455

336-
#[cfg(not(feature = "mysql"))] // FIXME: Figure out how to handle tests that modify schema
456+
#[cfg(any(feature = "postgres", feature = "sqlite", feature = "mysql"))]
337457
fn setup_test_table(conn: &TestConnection) {
338458
use crate::schema_dsl::*;
339459

@@ -374,6 +494,16 @@ fn setup_test_table(conn: &TestConnection) {
374494
.execute(conn)
375495
.unwrap();
376496

497+
create_table(
498+
"has_date",
499+
(
500+
integer("id").primary_key().auto_increment(),
501+
date("date").not_null(),
502+
),
503+
)
504+
.execute(conn)
505+
.unwrap();
506+
377507
create_table(
378508
"nullable_date_and_time",
379509
(

diesel_tests/tests/schema_dsl/structures.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ where
8484
{
8585
fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
8686
out.unsafe_to_cache_prepared();
87-
out.push_sql("CREATE TABLE ");
87+
out.push_sql("CREATE TABLE IF NOT EXISTS ");
8888
out.push_identifier(self.name)?;
8989
out.push_sql(" (");
9090
self.columns.walk_ast(out.reborrow())?;

0 commit comments

Comments
 (0)