diesel/query_builder/
debug_query.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use super::{AstPass, QueryBuilder, QueryFragment};
use crate::backend::Backend;
use std::fmt::{self, Debug, Display};
use std::marker::PhantomData;

/// A struct that implements `fmt::Display` and `fmt::Debug` to show the SQL
/// representation of a query.
///
/// The `Display` implementation will be the exact query sent to the server,
/// plus a comment with the values of the bind parameters. The `Debug`
/// implementation is more structured, and able to be pretty printed.
///
/// See [`debug_query`] for usage examples.
///
/// [`debug_query`]: crate::query_builder::debug_query()
pub struct DebugQuery<'a, T: 'a, DB> {
    pub(crate) query: &'a T,
    _marker: PhantomData<DB>,
}

impl<'a, T, DB> DebugQuery<'a, T, DB> {
    pub(crate) fn new(query: &'a T) -> Self {
        DebugQuery {
            query,
            _marker: PhantomData,
        }
    }
}

fn serialize_query<DB>(query: &dyn QueryFragment<DB>) -> Result<String, fmt::Error>
where
    DB: Backend + Default,
    DB::QueryBuilder: Default,
{
    let mut query_builder = DB::QueryBuilder::default();
    let backend = DB::default();
    QueryFragment::<DB>::to_sql(query, &mut query_builder, &backend).map_err(|_| fmt::Error)?;
    Ok(query_builder.finish())
}

fn display<DB>(query: &dyn QueryFragment<DB>, f: &mut fmt::Formatter<'_>) -> fmt::Result
where
    DB: Backend + Default,
    DB::QueryBuilder: Default,
{
    let debug_binds = DebugBinds::<DB>::new(query);
    let query = serialize_query(query)?;
    write!(f, "{} -- binds: {:?}", query, debug_binds)
}

fn debug<DB>(query: &dyn QueryFragment<DB>, f: &mut fmt::Formatter<'_>) -> fmt::Result
where
    DB: Backend + Default,
    DB::QueryBuilder: Default,
{
    let debug_binds = DebugBinds::<DB>::new(query);
    let query = serialize_query(query)?;
    f.debug_struct("Query")
        .field("sql", &query)
        .field("binds", &debug_binds)
        .finish()
}

impl<T, DB> Display for DebugQuery<'_, T, DB>
where
    DB: Backend + Default,
    DB::QueryBuilder: Default,
    T: QueryFragment<DB>,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        display(self.query, f)
    }
}

impl<T, DB> Debug for DebugQuery<'_, T, DB>
where
    DB: Backend + Default,
    DB::QueryBuilder: Default,
    T: QueryFragment<DB>,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        debug(self.query, f)
    }
}

/// A struct that implements `fmt::Debug` by walking the given AST and writing
/// the `fmt::Debug` implementation of each bind parameter.
pub(crate) struct DebugBinds<'a, DB> {
    query: &'a dyn QueryFragment<DB>,
}

impl<'a, DB> DebugBinds<'a, DB>
where
    DB: Backend,
{
    fn new(query: &'a dyn QueryFragment<DB>) -> Self {
        DebugBinds { query }
    }
}

impl<DB> Debug for DebugBinds<'_, DB>
where
    DB: Backend + Default,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let backend = DB::default();
        let mut buffer = Vec::new();
        let ast_pass = AstPass::debug_binds(&mut buffer, &backend);
        self.query.walk_ast(ast_pass).map_err(|_| fmt::Error)?;
        format_list(f, &buffer)
    }
}

fn format_list<'b>(f: &mut fmt::Formatter<'_>, entries: &[Box<dyn Debug + 'b>]) -> fmt::Result {
    let mut list = f.debug_list();
    for entry in entries {
        list.entry(entry);
    }
    list.finish()
}