Skip to content

Commit f5b15e5

Browse files
authored
Merge pull request diesel-rs#2260 from weiznich/fix/2258
Fix diesel-rs#2258
2 parents bc6110d + 52562c1 commit f5b15e5

File tree

3 files changed

+200
-1
lines changed

3 files changed

+200
-1
lines changed

diesel/src/query_builder/debug_query.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::backend::Backend;
1616
///
1717
/// [`debug_query`]: ../fn.debug_query.html
1818
pub struct DebugQuery<'a, T: 'a, DB> {
19-
query: &'a T,
19+
pub(crate) query: &'a T,
2020
_marker: PhantomData<DB>,
2121
}
2222

diesel/src/query_builder/insert_statement/mod.rs

+113
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ pub(crate) use self::column_list::ColumnList;
55
pub(crate) use self::insert_from_select::InsertFromSelect;
66

77
use std::any::*;
8+
#[cfg(feature = "sqlite")]
9+
use std::fmt::{self, Debug, Display};
810
use std::marker::PhantomData;
911

1012
use super::returning_clause::*;
@@ -227,6 +229,62 @@ where
227229
}
228230
}
229231

232+
#[cfg(feature = "sqlite")]
233+
impl<'a, T, U, Op> Display for DebugQuery<'a, InsertStatement<T, BatchInsert<'a, U, T>, Op>, Sqlite>
234+
where
235+
&'a U: Insertable<T>,
236+
for<'b> DebugQuery<'b, InsertStatement<T, <&'a U as Insertable<T>>::Values, Op>, Sqlite>:
237+
Display,
238+
T: Copy,
239+
Op: Copy,
240+
{
241+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
242+
writeln!(f, "BEGIN;")?;
243+
for record in self.query.records.records {
244+
let stmt = InsertStatement::new(
245+
self.query.target,
246+
record.values(),
247+
self.query.operator,
248+
self.query.returning,
249+
);
250+
251+
writeln!(f, "{}", crate::debug_query::<Sqlite, _>(&stmt))?;
252+
}
253+
writeln!(f, "COMMIT;")?;
254+
Ok(())
255+
}
256+
}
257+
258+
#[cfg(feature = "sqlite")]
259+
impl<'a, T, U, Op> Debug for DebugQuery<'a, InsertStatement<T, BatchInsert<'a, U, T>, Op>, Sqlite>
260+
where
261+
&'a U: Insertable<T>,
262+
for<'b> DebugQuery<'b, InsertStatement<T, <&'a U as Insertable<T>>::Values, Op>, Sqlite>:
263+
Display,
264+
T: Copy,
265+
Op: Copy,
266+
{
267+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
268+
let mut statements = Vec::with_capacity(self.query.records.records.len() + 2);
269+
statements.push("BEGIN".into());
270+
for record in self.query.records.records {
271+
let stmt = InsertStatement::new(
272+
self.query.target,
273+
record.values(),
274+
self.query.operator,
275+
self.query.returning,
276+
);
277+
statements.push(format!("{}", crate::debug_query::<Sqlite, _>(&stmt)));
278+
}
279+
statements.push("COMMIT".into());
280+
281+
f.debug_struct("Query")
282+
.field("sql", &statements)
283+
.field("binds", &[] as &[i32; 0])
284+
.finish()
285+
}
286+
}
287+
230288
#[cfg(feature = "sqlite")]
231289
impl<T, U, Op> ExecuteDsl<SqliteConnection>
232290
for InsertStatement<T, OwnedBatchInsert<ValuesClause<U, T>, T>, Op>
@@ -249,6 +307,61 @@ where
249307
}
250308
}
251309

310+
#[cfg(feature = "sqlite")]
311+
impl<'a, T, U, Op> Display
312+
for DebugQuery<'a, InsertStatement<T, OwnedBatchInsert<ValuesClause<U, T>, T>, Op>, Sqlite>
313+
where
314+
for<'b> DebugQuery<'b, InsertStatement<T, &'b ValuesClause<U, T>, Op>, Sqlite>: Display,
315+
T: Copy,
316+
Op: Copy,
317+
{
318+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
319+
writeln!(f, "BEGIN;")?;
320+
for value in &self.query.records.values {
321+
let stmt = InsertStatement::new(
322+
self.query.target,
323+
value,
324+
self.query.operator,
325+
self.query.returning,
326+
);
327+
328+
writeln!(f, "{}", crate::debug_query::<Sqlite, _>(&stmt))?;
329+
}
330+
writeln!(f, "COMMIT;")?;
331+
Ok(())
332+
}
333+
}
334+
335+
#[cfg(feature = "sqlite")]
336+
impl<'a, T, U, Op> Debug
337+
for DebugQuery<'a, InsertStatement<T, OwnedBatchInsert<ValuesClause<U, T>, T>, Op>, Sqlite>
338+
where
339+
for<'b> DebugQuery<'b, InsertStatement<T, &'b ValuesClause<U, T>, Op>, Sqlite>: Display,
340+
T: Copy,
341+
Op: Copy,
342+
{
343+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
344+
let mut statements = Vec::with_capacity(self.query.records.values.len() + 2);
345+
statements.push("BEGIN".into());
346+
347+
for value in &self.query.records.values {
348+
let stmt = InsertStatement::new(
349+
self.query.target,
350+
value,
351+
self.query.operator,
352+
self.query.returning,
353+
);
354+
statements.push(format!("{}", crate::debug_query::<Sqlite, _>(&stmt)));
355+
}
356+
statements.push("COMMIT".into());
357+
358+
f.debug_struct("Query")
359+
.field("sql", &statements)
360+
.field("binds", &[] as &[i32; 0])
361+
.finish()
362+
}
363+
}
364+
252365
impl<T, U, Op, Ret> QueryId for InsertStatement<T, U, Op, Ret> {
253366
type QueryId = ();
254367

diesel_tests/tests/debug/mod.rs

+86
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,89 @@ fn test_debug_output() {
2929
)
3030
}
3131
}
32+
33+
#[test]
34+
fn test_debug_batch_insert() {
35+
// This test ensures that we've implemented `debug_query` for batch insert
36+
// on sqlite
37+
// This requires a separate impl because it's more than one sql statement that
38+
// is executed
39+
40+
use schema::users::dsl::*;
41+
42+
let values = vec![
43+
(name.eq("Sean"), hair_color.eq(Some("black"))),
44+
(name.eq("Tess"), hair_color.eq(None::<&str>)),
45+
];
46+
let borrowed_command = insert_into(users).values(&values);
47+
let borrowed_sql_display = debug_query::<TestBackend, _>(&borrowed_command).to_string();
48+
let borrowed_sql_debug = format!("{:?}", debug_query::<TestBackend, _>(&borrowed_command));
49+
50+
let owned_command = insert_into(users).values(values);
51+
let owned_sql_display = debug_query::<TestBackend, _>(&owned_command).to_string();
52+
let owned_sql_debug = format!("{:?}", debug_query::<TestBackend, _>(&owned_command));
53+
54+
if cfg!(feature = "postgres") {
55+
assert_eq!(
56+
borrowed_sql_display,
57+
r#"INSERT INTO "users" ("name", "hair_color") VALUES ($1, $2), ($3, $4) -- binds: ["Sean", Some("black"), "Tess", None]"#
58+
);
59+
assert_eq!(
60+
borrowed_sql_debug,
61+
r#"Query { sql: "INSERT INTO \"users\" (\"name\", \"hair_color\") VALUES ($1, $2), ($3, $4)", binds: ["Sean", Some("black"), "Tess", None] }"#
62+
);
63+
64+
assert_eq!(
65+
owned_sql_display,
66+
r#"INSERT INTO "users" ("name", "hair_color") VALUES ($1, $2), ($3, $4) -- binds: ["Sean", Some("black"), "Tess", None]"#
67+
);
68+
assert_eq!(
69+
owned_sql_debug,
70+
r#"Query { sql: "INSERT INTO \"users\" (\"name\", \"hair_color\") VALUES ($1, $2), ($3, $4)", binds: ["Sean", Some("black"), "Tess", None] }"#
71+
);
72+
} else if cfg!(feature = "sqlite") {
73+
assert_eq!(
74+
borrowed_sql_display,
75+
r#"BEGIN;
76+
INSERT INTO `users` (`name`, `hair_color`) VALUES (?, ?) -- binds: ["Sean", Some("black")]
77+
INSERT INTO `users` (`name`, `hair_color`) VALUES (?, ?) -- binds: ["Tess", None]
78+
COMMIT;
79+
"#
80+
);
81+
assert_eq!(
82+
borrowed_sql_debug,
83+
r#"Query { sql: ["BEGIN", "INSERT INTO `users` (`name`, `hair_color`) VALUES (?, ?) -- binds: [\"Sean\", Some(\"black\")]", "INSERT INTO `users` (`name`, `hair_color`) VALUES (?, ?) -- binds: [\"Tess\", None]", "COMMIT"], binds: [] }"#
84+
);
85+
86+
assert_eq!(
87+
owned_sql_display,
88+
r#"BEGIN;
89+
INSERT INTO `users` (`name`, `hair_color`) VALUES (?, ?) -- binds: ["Sean", Some("black")]
90+
INSERT INTO `users` (`name`, `hair_color`) VALUES (?, ?) -- binds: ["Tess", None]
91+
COMMIT;
92+
"#
93+
);
94+
assert_eq!(
95+
owned_sql_debug,
96+
r#"Query { sql: ["BEGIN", "INSERT INTO `users` (`name`, `hair_color`) VALUES (?, ?) -- binds: [\"Sean\", Some(\"black\")]", "INSERT INTO `users` (`name`, `hair_color`) VALUES (?, ?) -- binds: [\"Tess\", None]", "COMMIT"], binds: [] }"#
97+
);
98+
} else {
99+
assert_eq!(
100+
borrowed_sql_display,
101+
r#"INSERT INTO `users` (`name`, `hair_color`) VALUES (?, ?), (?, ?) -- binds: ["Sean", Some("black"), "Tess", None]"#
102+
);
103+
assert_eq!(
104+
borrowed_sql_debug,
105+
r#"Query { sql: "INSERT INTO `users` (`name`, `hair_color`) VALUES (?, ?), (?, ?)", binds: ["Sean", Some("black"), "Tess", None] }"#
106+
);
107+
108+
assert_eq!(
109+
owned_sql_display,
110+
r#"INSERT INTO `users` (`name`, `hair_color`) VALUES (?, ?), (?, ?) -- binds: ["Sean", Some("black"), "Tess", None]"#
111+
);
112+
assert_eq!(
113+
owned_sql_debug,
114+
r#"Query { sql: "INSERT INTO `users` (`name`, `hair_color`) VALUES (?, ?), (?, ?)", binds: ["Sean", Some("black"), "Tess", None] }"#
115+
);
116+
}
117+
}

0 commit comments

Comments
 (0)