Skip to content

Commit ba9be64

Browse files
committed
Add debugging query builder and open up public api with macros
1 parent 3713944 commit ba9be64

6 files changed

Lines changed: 113 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,15 @@ All user visible changes to this project will be documented in this file.
33
This project adheres to [Semantic Versioning](http://semver.org/), as described
44
for Rust libraries in [RFC #1105](https://github.com/rust-lang/rfcs/blob/master/text/1105-api-evolution.md)
55

6+
## Unreleased
7+
8+
### Added
9+
10+
* Add DebugQueryBuilder to build sql without requiring a connection.
11+
12+
* Add print_sql! and debug_sql! macros to print out and return sql strings from
13+
QueryFragments.
14+
615
## [0.3.0] 2015-12-04
716

817
### Changed

diesel/src/macros.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,3 +346,53 @@ macro_rules! join_through {
346346
}
347347
}
348348
}
349+
350+
/// Takes a query QueryFragment expression as an argument and returns a string
351+
/// of SQL with placeholders for the dynamic values.
352+
///
353+
/// # Example
354+
///
355+
/// ### Returning SQL from a count statment:
356+
/// #
357+
/// # ```rust
358+
/// # // example requires setup for users table
359+
/// # use diesel::users::dsl::*;
360+
/// # use diesel::query_builder::QueryFragment;
361+
/// #
362+
/// # fn main() {
363+
/// let sql = debug_sql!(users.count());
364+
/// assert_eq!(sql, "SELECT COUNT(*) FROM users");
365+
/// # }
366+
/// # ```
367+
#[macro_export]
368+
macro_rules! debug_sql {
369+
($query:expr) => {{
370+
use diesel::query_builder::QueryFragment;
371+
let mut query_builder = DebugQueryBuilder::new();
372+
QueryFragment::to_sql(&$query, &mut query_builder).unwrap();
373+
query_builder.sql
374+
}};
375+
}
376+
377+
/// Takes takes a query QueryFragment expression as an argument and prints out
378+
/// the SQL with placeholders for the dynamic values.
379+
///
380+
/// # Example
381+
///
382+
/// ### Printing SQL from a count statment:
383+
/// #
384+
/// # ```rust
385+
/// # // example requires setup for users table
386+
/// # use diesel::users::dsl::*;
387+
/// # use diesel::query_builder::QueryFragment;
388+
/// #
389+
/// # fn main() {
390+
/// print_sql!(users.count());
391+
/// # }
392+
/// # ```
393+
#[macro_export]
394+
macro_rules! print_sql {
395+
($query:expr) => {
396+
println!("{}", &debug_sql!($query));
397+
};
398+
}

diesel/src/query_builder/debug.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use super::{QueryBuilder, BuildQueryResult};
2+
use types::NativeSqlType;
3+
4+
#[doc(hidden)]
5+
pub struct DebugQueryBuilder {
6+
pub sql: String,
7+
pub bind_types: Vec<u32>,
8+
bind_idx: u32,
9+
}
10+
11+
impl DebugQueryBuilder {
12+
pub fn new() -> Self {
13+
DebugQueryBuilder {
14+
sql: String::new(),
15+
bind_types: Vec::new(),
16+
bind_idx: 0,
17+
}
18+
}
19+
}
20+
21+
impl QueryBuilder for DebugQueryBuilder {
22+
fn push_sql(&mut self, sql: &str) {
23+
self.sql.push_str(sql);
24+
}
25+
26+
fn push_identifier(&mut self, identifier: &str) -> BuildQueryResult {
27+
Ok(self.push_sql(&identifier))
28+
}
29+
30+
fn push_bound_value(&mut self, _tpe: &NativeSqlType, _bind: Option<Vec<u8>>) {
31+
self.bind_idx += 1;
32+
let sql = format!("${}", self.bind_idx);
33+
self.push_sql(&sql);
34+
}
35+
}

diesel/src/query_builder/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Contains traits responsible for the actual construction of SQL statements
22
#[doc(hidden)]
33
pub mod pg;
4+
pub mod debug;
45

56
mod delete_statement;
67
mod functions;

diesel_tests/tests/debug/mod.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use diesel::*;
2+
use diesel::query_builder::debug::DebugQueryBuilder;
3+
use diesel::query_builder::update;
4+
5+
#[test]
6+
fn test_debug_count_output() {
7+
use schema::users::dsl::*;
8+
let sql = debug_sql!(users.count());
9+
assert_eq!(sql, "SELECT COUNT(*) FROM users");
10+
}
11+
12+
#[test]
13+
fn test_debug_output() {
14+
use schema::users::dsl::*;
15+
let command = update(users.filter(id.eq(1))).set(name.eq("new_name"));
16+
assert_eq!(debug_sql!(command), "UPDATE users SET name = $1 WHERE users.id = $2")
17+
}

diesel_tests/tests/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ mod select;
2424
mod transactions;
2525
mod types;
2626
mod types_roundtrip;
27+
mod debug;

0 commit comments

Comments
 (0)