use std::fmt;
use super::entry::QueryOperation;
#[derive(Debug, Clone)]
pub struct QueryDebugInfo {
pub table: String,
pub operation: QueryOperation,
pub conditions: Vec<String>,
pub order_by: Vec<String>,
pub group_by: Vec<String>,
pub select: Vec<String>,
pub joins: Vec<String>,
pub limit: Option<u64>,
pub offset: Option<u64>,
pub sql: String,
pub params: Vec<String>,
}
impl QueryDebugInfo {
pub fn new(table: impl Into<String>) -> Self {
Self {
table: table.into(),
operation: QueryOperation::Select,
conditions: Vec::new(),
order_by: Vec::new(),
group_by: Vec::new(),
select: vec!["*".to_string()],
joins: Vec::new(),
limit: None,
offset: None,
sql: String::new(),
params: Vec::new(),
}
}
pub fn with_operation(mut self, op: QueryOperation) -> Self {
self.operation = op;
self
}
pub fn add_condition(&mut self, condition: impl Into<String>) {
self.conditions.push(condition.into());
}
pub fn add_order_by(&mut self, order: impl Into<String>) {
self.order_by.push(order.into());
}
pub fn with_sql(mut self, sql: impl Into<String>) -> Self {
self.sql = sql.into();
self
}
pub fn with_params(mut self, params: Vec<String>) -> Self {
self.params = params;
self
}
}
impl fmt::Display for QueryDebugInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
const DEBUG_PREVIEW_BANNER: &str =
"-- DEBUG PREVIEW (not executable, values are approximate)";
writeln!(f, "═══════════════════════════════════════════════════")?;
writeln!(f, "TIDEORM QUERY DEBUG")?;
writeln!(f, "═══════════════════════════════════════════════════")?;
writeln!(f, "Table: {}", self.table)?;
writeln!(f, "Operation: {}", self.operation)?;
if !self.select.is_empty() && self.select != vec!["*".to_string()] {
writeln!(f, "Select: {}", self.select.join(", "))?;
}
if !self.conditions.is_empty() {
writeln!(f, "Conditions:")?;
for cond in &self.conditions {
writeln!(f, " - {}", cond)?;
}
}
if !self.joins.is_empty() {
writeln!(f, "Joins:")?;
for join in &self.joins {
writeln!(f, " - {}", join)?;
}
}
if !self.order_by.is_empty() {
writeln!(f, "Order By: {}", self.order_by.join(", "))?;
}
if !self.group_by.is_empty() {
writeln!(f, "Group By: {}", self.group_by.join(", "))?;
}
if let Some(limit) = self.limit {
write!(f, "Limit: {}", limit)?;
if let Some(offset) = self.offset {
write!(f, " (offset: {})", offset)?;
}
writeln!(f)?;
}
if !self.sql.is_empty() {
writeln!(f, "───────────────────────────────────────────────────")?;
if self.sql.starts_with(DEBUG_PREVIEW_BANNER) {
writeln!(f, "SQL Preview (non-executable):")?;
} else {
writeln!(f, "SQL:")?;
}
for line in self.sql.lines() {
writeln!(f, " {}", line)?;
}
}
if !self.params.is_empty() {
writeln!(f, "Params: {:?}", self.params)?;
}
write!(f, "═══════════════════════════════════════════════════")
}
}