diff --git a/src/query/ast/src/parser/error.rs b/src/query/ast/src/parser/error.rs index 4837424dbc172..16e3bf716f0c7 100644 --- a/src/query/ast/src/parser/error.rs +++ b/src/query/ast/src/parser/error.rs @@ -255,7 +255,7 @@ pub fn display_parser_error(error: Error, source: &str) -> String { format!("unexpected `{span_text}`") }; if let Some(suggestion) = has_suggestion { - msg += &format!(". {}", suggestion); + write!(msg, ". {}", suggestion).unwrap(); labels = vec![(inner.span, msg)]; // Return early to skip context labels when we have intelligent suggestions diff --git a/src/query/service/src/physical_plans/format/common.rs b/src/query/service/src/physical_plans/format/common.rs index 22e353080d9fb..885e5a92217a2 100644 --- a/src/query/service/src/physical_plans/format/common.rs +++ b/src/query/service/src/physical_plans/format/common.rs @@ -13,6 +13,7 @@ // limitations under the License. use std::collections::HashMap; +use std::fmt::Write; use databend_common_ast::ast::FormatTreeNode; use databend_common_base::base::format_byte_size; @@ -70,64 +71,74 @@ pub fn part_stats_info_to_format_tree(info: &PartStatistics) -> Vec 0 { - blocks_pruning_description += &format!( + write!( + blocks_pruning_description, "range pruning: {} to {}{}", info.pruning_stats.blocks_range_pruning_before, info.pruning_stats.blocks_range_pruning_after, format_pruning_cost_suffix(info.pruning_stats.blocks_range_pruning_cost) - ); + ) + .unwrap(); } // bloom pruning status. if info.pruning_stats.blocks_bloom_pruning_before > 0 { if !blocks_pruning_description.is_empty() { - blocks_pruning_description += ", "; + blocks_pruning_description.push_str(", "); } - blocks_pruning_description += &format!( + write!( + blocks_pruning_description, "bloom pruning: {} to {}{}", info.pruning_stats.blocks_bloom_pruning_before, info.pruning_stats.blocks_bloom_pruning_after, format_pruning_cost_suffix(info.pruning_stats.blocks_bloom_pruning_cost) - ); + ) + .unwrap(); } // inverted index pruning status. if info.pruning_stats.blocks_inverted_index_pruning_before > 0 { if !blocks_pruning_description.is_empty() { - blocks_pruning_description += ", "; + blocks_pruning_description.push_str(", "); } - blocks_pruning_description += &format!( + write!( + blocks_pruning_description, "inverted pruning: {} to {}{}", info.pruning_stats.blocks_inverted_index_pruning_before, info.pruning_stats.blocks_inverted_index_pruning_after, format_pruning_cost_suffix(info.pruning_stats.blocks_inverted_index_pruning_cost) - ); + ) + .unwrap(); } // topn pruning status. if info.pruning_stats.blocks_topn_pruning_before > 0 { if !blocks_pruning_description.is_empty() { - blocks_pruning_description += ", "; + blocks_pruning_description.push_str(", "); } - blocks_pruning_description += &format!( + write!( + blocks_pruning_description, "topn pruning: {} to {}{}", info.pruning_stats.blocks_topn_pruning_before, info.pruning_stats.blocks_topn_pruning_after, format_pruning_cost_suffix(info.pruning_stats.blocks_topn_pruning_cost) - ); + ) + .unwrap(); } // vector index pruning status. if info.pruning_stats.blocks_vector_index_pruning_before > 0 { if !blocks_pruning_description.is_empty() { - blocks_pruning_description += ", "; + blocks_pruning_description.push_str(", "); } - blocks_pruning_description += &format!( + write!( + blocks_pruning_description, "vector pruning: {} to {}{}", info.pruning_stats.blocks_vector_index_pruning_before, info.pruning_stats.blocks_vector_index_pruning_after, format_pruning_cost_suffix(info.pruning_stats.blocks_vector_index_pruning_cost) - ); + ) + .unwrap(); } // Combine segment pruning and blocks pruning descriptions if any @@ -137,19 +148,26 @@ pub fn part_stats_info_to_format_tree(info: &PartStatistics) -> Vec 0 { - pruning_description += &format!( + write!( + pruning_description, "segments: ", info.pruning_stats.segments_range_pruning_before, info.pruning_stats.segments_range_pruning_after, format_pruning_cost_suffix(info.pruning_stats.segments_range_pruning_cost) - ); + ) + .unwrap(); } if !blocks_pruning_description.is_empty() { if !pruning_description.is_empty() { - pruning_description += ", "; + pruning_description.push_str(", "); } - pruning_description += &format!("blocks: <{}>", blocks_pruning_description); + write!( + pruning_description, + "blocks: <{}>", + blocks_pruning_description + ) + .unwrap(); } items.push(FormatTreeNode::new(format!( diff --git a/src/query/sql/src/planner/optimizer/pipeline/trace/trace.rs b/src/query/sql/src/planner/optimizer/pipeline/trace/trace.rs index 9d8e80ade3eed..9106a25192a6f 100644 --- a/src/query/sql/src/planner/optimizer/pipeline/trace/trace.rs +++ b/src/query/sql/src/planner/optimizer/pipeline/trace/trace.rs @@ -13,6 +13,7 @@ // limitations under the License. use std::collections::BTreeMap; +use std::fmt::Write; use std::time::Duration; use databend_common_exception::Result; @@ -286,10 +287,12 @@ impl OptimizerTraceCollector { (0, 0) }; - summary.push_str(&format!( - "[{}] {}: {} ({:.2?})\n", + writeln!( + summary, + "[{}] {}: {} ({:.2?})", status_symbol, optimizer.index, optimizer.name, optimizer.time - )); + ) + .unwrap(); if total_rules > 0 { let applied_percentage = if total_rules > 0 { @@ -298,10 +301,12 @@ impl OptimizerTraceCollector { 0 }; - summary.push_str(&format!( - " └── Rules: {}/{} Applied ({}%)\n", + writeln!( + summary, + " └── Rules: {}/{} Applied ({}%)", applied_rules, total_rules, applied_percentage - )); + ) + .unwrap(); // Add detailed rules summary if available if let Some(optimizer_rules) = rules.get(&optimizer.name) { @@ -312,7 +317,7 @@ impl OptimizerTraceCollector { // Add indentation to rules summary for line in rules_summary.lines() { if !line.trim().is_empty() { - summary.push_str(&format!(" {}\n", line)); + writeln!(summary, " {}", line).unwrap(); } } } @@ -340,16 +345,18 @@ impl OptimizerTraceCollector { let mut detail = String::new(); // Add basic optimizer information - detail.push_str(&format!( + write!( + detail, "[{}] {}: {} ({:.2?})\n\n", status_symbol, optimizer.index, optimizer.name, optimizer.time - )); + ) + .unwrap(); // Add expression changes if any if optimizer.had_effect && !optimizer.diff.is_empty() { detail.push_str(" Changes:\n"); for line in optimizer.diff.lines() { - detail.push_str(&format!(" {}\n", line)); + writeln!(detail, " {}", line).unwrap(); } detail.push('\n'); } @@ -389,15 +396,17 @@ impl OptimizerTraceCollector { return report; } - report.push_str(&format!("[{}] Rules Summary:\n", optimizer.name)); + writeln!(report, "[{}] Rules Summary:", optimizer.name).unwrap(); // List all rules with their status for rule in &all_rules { let status_symbol = if rule.had_effect { "✓" } else { "✗" }; - report.push_str(&format!( - " [{}] {}.{}: {} ({:.2?})\n", + writeln!( + report, + " [{}] {}.{}: {} ({:.2?})", status_symbol, optimizer.index, rule.sequence, rule.name, rule.time - )); + ) + .unwrap(); } report.push('\n'); @@ -418,17 +427,21 @@ impl OptimizerTraceCollector { }; // Add statistics to report - report.push_str(&format!( - " Total Applied Rules: {}/{} ({}%)\n", + writeln!( + report, + " Total Applied Rules: {}/{} ({}%)", applied_rules, total_rules, applied_percentage - )); + ) + .unwrap(); - report.push_str(&format!( + write!( + report, " Total Non-Applied Rules: {}/{} ({}%)\n\n", total_rules - applied_rules, total_rules, non_applied_percentage - )); + ) + .unwrap(); report } @@ -454,16 +467,18 @@ impl OptimizerTraceCollector { for rule in applied_rules { // Always use checkmark since we only show rules that had an effect let status_symbol = "✓"; - report.push_str(&format!( - " [{}] {}.{}: {}.{} ({:.2?})\n", + writeln!( + report, + " [{}] {}.{}: {}.{} ({:.2?})", status_symbol, optimizer.index, rule.sequence, optimizer.name, rule.name, rule.time - )); + ) + .unwrap(); // Add expression changes if available if !rule.diff.is_empty() { report.push_str(" Changes:\n"); for line in rule.diff.lines() { - report.push_str(&format!(" {}\n", line)); + writeln!(report, " {}", line).unwrap(); } }