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 fmt_query<DB>(
45 query: &dyn QueryFragment<DB>,
46 f: &mut fmt::Formatter<'_>,
47 formatter: fn(String, &DebugBinds<'_>, f: &mut fmt::Formatter<'_>) -> fmt::Result,
48) -> fmt::Result
49where
50 DB: Backend + Default,
51 DB::QueryBuilder: Default,
52{
53 let backend = DB::default();
54 let mut buffer = Vec::new();
55 let ast_pass = AstPass::debug_binds(&mut buffer, &backend);
56 query.walk_ast(ast_pass).map_err(|_| fmt::Error)?;
57 let debug_binds = DebugBinds::new(&buffer);
58 let query = serialize_query(query)?;
59 formatter(query, &debug_binds, f)
60}
61
62pub(crate) fn display(
63 query: String,
64 debug_binds: &DebugBinds<'_>,
65 f: &mut fmt::Formatter<'_>,
66) -> fmt::Result {
67 f.write_fmt(format_args!("{0} -- binds: {1:?}", query, debug_binds))write!(f, "{query} -- binds: {debug_binds:?}")
68}
69
70pub(crate) fn debug(
71 query: String,
72 debug_binds: &DebugBinds<'_>,
73 f: &mut fmt::Formatter<'_>,
74) -> fmt::Result {
75 f.debug_struct("Query")
76 .field("sql", &query)
77 .field("binds", &debug_binds)
78 .finish()
79}
80
81impl<T, DB> Display for DebugQuery<'_, T, DB>
82where
83 DB: Backend + Default,
84 DB::QueryBuilder: Default,
85 T: QueryFragment<DB>,
86{
87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 fmt_query(self.query, f, display)
89 }
90}
91
92impl<T, DB> Debug for DebugQuery<'_, T, DB>
93where
94 DB: Backend + Default,
95 DB::QueryBuilder: Default,
96 T: QueryFragment<DB>,
97{
98 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99 fmt_query(self.query, f, debug)
100 }
101}
102
103pub(crate) struct DebugBinds<'a> {
106 binds: &'a [Box<dyn Debug + 'a>],
107}
108
109impl<'a> DebugBinds<'a> {
110 pub(crate) fn new(binds: &'a [Box<dyn Debug + 'a>]) -> Self {
111 DebugBinds { binds }
112 }
113}
114
115impl Debug for DebugBinds<'_> {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 format_list(f, self.binds)
118 }
119}
120
121fn format_list<'b>(f: &mut fmt::Formatter<'_>, entries: &[Box<dyn Debug + 'b>]) -> fmt::Result {
122 let mut list = f.debug_list();
123 for entry in entries {
124 list.entry(entry);
125 }
126 list.finish()
127}