use std::fmt;
use serde::Serialize;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub enum FindingKind {
RelationPerRow,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct Finding {
pub relation: String,
pub kind: FindingKind,
pub parent_query: String,
pub child_queries: usize,
pub recommendation: String,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)]
pub struct Report {
pub findings: Vec<Finding>,
}
impl Report {
#[must_use]
pub fn has_findings(&self) -> bool {
!self.findings.is_empty()
}
#[must_use]
pub fn len(&self) -> usize {
self.findings.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.findings.is_empty()
}
}
impl fmt::Display for Report {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.findings.is_empty() {
return write!(formatter, "no N+1 findings");
}
writeln!(formatter, "{} N+1 finding(s):", self.findings.len())?;
for (index, finding) in self.findings.iter().enumerate() {
writeln!(
formatter,
" {index}. relation `{}`: {} per-row child queries after parent query `{}`",
finding.relation, finding.child_queries, finding.parent_query
)?;
writeln!(formatter, " recommendation: {}", finding.recommendation)?;
}
Ok(())
}
}