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