Skip to content

Commit

Permalink
Merge pull request #4417 from Turbo87/mono
Browse files Browse the repository at this point in the history
DebugBinds/Query: Reduce monomorphization overhead
  • Loading branch information
weiznich authored Jan 3, 2025
2 parents 3f69aa4 + 35c9f9f commit cec3cd0
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 32 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ jobs:
- name: Install sqlite (Linux)
if: runner.os == 'Linux' && matrix.backend == 'sqlite'
run: |
sudo apt-get update
sudo apt-get install -y libsqlite3-dev
echo "SQLITE_DATABASE_URL=/tmp/test.db" >> $GITHUB_ENV
- name: Install mysql (Linux)
Expand Down
85 changes: 53 additions & 32 deletions diesel/src/query_builder/debug_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,48 @@ impl<'a, T, DB> DebugQuery<'a, T, DB> {
}
}

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 {
let mut query_builder = DB::QueryBuilder::default();
let backend = DB::default();
QueryFragment::<DB>::to_sql(self.query, &mut query_builder, &backend)
.map_err(|_| fmt::Error)?;
let debug_binds = DebugBinds::<_, DB>::new(self.query);
write!(f, "{} -- binds: {:?}", query_builder.finish(), debug_binds)
display(self.query, f)
}
}

Expand All @@ -50,50 +79,42 @@ where
T: QueryFragment<DB>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut query_builder = DB::QueryBuilder::default();
let backend = DB::default();
QueryFragment::<DB>::to_sql(self.query, &mut query_builder, &backend)
.map_err(|_| fmt::Error)?;
let debug_binds = DebugBinds::<_, DB>::new(self.query);
f.debug_struct("Query")
.field("sql", &query_builder.finish())
.field("binds", &debug_binds)
.finish()
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, T: 'a, DB> {
query: &'a T,
_marker: PhantomData<DB>,
pub(crate) struct DebugBinds<'a, DB> {
query: &'a dyn QueryFragment<DB>,
}

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

impl<T, DB> Debug for DebugBinds<'_, T, DB>
impl<DB> Debug for DebugBinds<'_, DB>
where
DB: Backend + Default,
T: QueryFragment<DB>,
{
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)
}
}

let mut list = f.debug_list();
for entry in buffer {
list.entry(&entry);
}
list.finish()?;
Ok(())
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()
}

0 comments on commit cec3cd0

Please sign in to comment.