diesel/query_builder/
debug_query.rs1use super::{AstPass, QueryBuilder, QueryFragment};
2use crate::backend::Backend;
3use std::fmt::{self, Debug, Display};
4use std::marker::PhantomData;
5
6pub struct DebugQuery<'a, T: 'a, DB> {
17 pub(crate) query: &'a T,
18 _marker: PhantomData<DB>,
19}
20
21impl<'a, T, DB> DebugQuery<'a, T, DB> {
22 pub(crate) fn new(query: &'a T) -> Self {
23 DebugQuery {
24 query,
25 _marker: PhantomData,
26 }
27 }
28}
29
30fn serialize_query<DB>(query: &dyn QueryFragment<DB>) -> Result<String, fmt::Error>
31where
32 DB: Backend + Default,
33 DB::QueryBuilder: Default,
34{
35 let mut query_builder = DB::QueryBuilder::default();
36 let backend = DB::default();
37 QueryFragment::<DB>::to_sql(query, &mut query_builder, &backend).map_err(|_| fmt::Error)?;
38 Ok(query_builder.finish())
39}
40
41fn fmt_query<DB>(
42 query: &dyn QueryFragment<DB>,
43 f: &mut fmt::Formatter<'_>,
44 formatter: fn(String, &DebugBinds<'_>, f: &mut fmt::Formatter<'_>) -> fmt::Result,
45) -> fmt::Result
46where
47 DB: Backend + Default,
48 DB::QueryBuilder: Default,
49{
50 let backend = DB::default();
51 let mut buffer = Vec::new();
52 let ast_pass = AstPass::debug_binds(&mut buffer, &backend);
53 query.walk_ast(ast_pass).map_err(|_| fmt::Error)?;
54 let debug_binds = DebugBinds::new(&buffer);
55 let query = serialize_query(query)?;
56 formatter(query, &debug_binds, f)
57}
58
59pub(crate) fn display(
60 query: String,
61 debug_binds: &DebugBinds<'_>,
62 f: &mut fmt::Formatter<'_>,
63) -> fmt::Result {
64 f.write_fmt(format_args!("{0} -- binds: {1:?}", query, debug_binds))write!(f, "{query} -- binds: {debug_binds:?}")
65}
66
67pub(crate) fn debug(
68 query: String,
69 debug_binds: &DebugBinds<'_>,
70 f: &mut fmt::Formatter<'_>,
71) -> fmt::Result {
72 f.debug_struct("Query")
73 .field("sql", &query)
74 .field("binds", &debug_binds)
75 .finish()
76}
77
78impl<T, DB> Display for DebugQuery<'_, T, DB>
79where
80 DB: Backend + Default,
81 DB::QueryBuilder: Default,
82 T: QueryFragment<DB>,
83{
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 fmt_query(self.query, f, display)
86 }
87}
88
89impl<T, DB> Debug for DebugQuery<'_, T, DB>
90where
91 DB: Backend + Default,
92 DB::QueryBuilder: Default,
93 T: QueryFragment<DB>,
94{
95 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96 fmt_query(self.query, f, debug)
97 }
98}
99
100pub(crate) struct DebugBinds<'a> {
103 binds: &'a [Box<dyn Debug + 'a>],
104}
105
106impl<'a> DebugBinds<'a> {
107 pub(crate) fn new(binds: &'a [Box<dyn Debug + 'a>]) -> Self {
108 DebugBinds { binds }
109 }
110}
111
112impl Debug for DebugBinds<'_> {
113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114 format_list(f, self.binds)
115 }
116}
117
118fn format_list<'b>(f: &mut fmt::Formatter<'_>, entries: &[Box<dyn Debug + 'b>]) -> fmt::Result {
119 let mut list = f.debug_list();
120 for entry in entries {
121 list.entry(entry);
122 }
123 list.finish()
124}