From 036235a51841d1083d32f001e970cb5b7f3aa2fe Mon Sep 17 00:00:00 2001 From: TcMits Date: Tue, 9 Sep 2025 17:41:08 +0700 Subject: [PATCH] clean 'print_query_result' --- cli/app.rs | 342 ++++++++++++++++++++--------------------------------- 1 file changed, 128 insertions(+), 214 deletions(-) diff --git a/cli/app.rs b/cli/app.rs index f72e2a6c6..41667b614 100644 --- a/cli/app.rs +++ b/cli/app.rs @@ -93,6 +93,60 @@ struct QueryStatistics { execute_time_elapsed_samples: Vec, } +macro_rules! row_step_result_query { + ($app:expr, $sql:expr, $rows:expr, $stats:expr, $row_handle:expr) => { + if $app.interrupt_count.load(Ordering::Acquire) > 0 { + println!("Query interrupted."); + return Ok(()); + } + + let start = Instant::now(); + match $rows.step() { + Ok(StepResult::Row) => { + if let Some(ref mut stats) = $stats { + stats.execute_time_elapsed_samples.push(start.elapsed()); + } + + $row_handle + } + Ok(StepResult::IO) => { + let start = Instant::now(); + $rows.run_once()?; + if let Some(ref mut stats) = $stats { + stats.io_time_elapsed_samples.push(start.elapsed()); + } + } + Ok(StepResult::Interrupt) => { + if let Some(ref mut stats) = $stats { + stats.execute_time_elapsed_samples.push(start.elapsed()); + } + break; + } + Ok(StepResult::Done) => { + if let Some(ref mut stats) = $stats { + stats.execute_time_elapsed_samples.push(start.elapsed()); + } + break; + } + Ok(StepResult::Busy) => { + if let Some(ref mut stats) = $stats { + stats.execute_time_elapsed_samples.push(start.elapsed()); + } + let _ = $app.writeln("database is busy"); + break; + } + Err(err) => { + if let Some(ref mut stats) = $stats { + stats.execute_time_elapsed_samples.push(start.elapsed()); + } + let report = miette::Error::from(err).with_source_code($sql.to_owned()); + let _ = $app.write_fmt(format_args!("{report:?}")); + break; + } + } + }; +} + impl Limbo { pub fn new() -> anyhow::Result<(Self, WorkerGuard)> { let opts = Opts::parse(); @@ -375,6 +429,13 @@ impl Limbo { self.writer.as_mut().unwrap().write_all(b"\n") } + fn write_null(&mut self) -> io::Result<()> { + self.writer + .as_mut() + .unwrap() + .write_all(self.opts.null_value.as_bytes()) + } + fn buffer_input(&mut self, line: &str) { self.input_buff.push_str(line); self.input_buff.push(' '); @@ -659,88 +720,35 @@ impl Limbo { OutputMode::List => { let mut headers_printed = false; loop { - if self.interrupt_count.load(Ordering::Acquire) > 0 { - println!("Query interrupted."); - return Ok(()); - } - - let start = Instant::now(); - - match rows.step() { - Ok(StepResult::Row) => { - if let Some(ref mut stats) = statistics { - stats.execute_time_elapsed_samples.push(start.elapsed()); - } - - // Print headers if enabled and not already printed - if self.opts.headers && !headers_printed { - for i in 0..rows.num_columns() { - if i > 0 { - let _ = self.write(b"|"); - } - let _ = self.write(rows.get_column_name(i).as_bytes()); - } - let _ = self.writeln(""); - headers_printed = true; - } - - let row = rows.row().unwrap(); - for (i, value) in row.get_values().enumerate() { + row_step_result_query!(self, sql, rows, statistics, { + // Print headers if enabled and not already printed + if self.opts.headers && !headers_printed { + for i in 0..rows.num_columns() { if i > 0 { let _ = self.write(b"|"); } - if matches!(value, Value::Null) { - let bytes = self.opts.null_value.clone(); - self.write(bytes.as_bytes())?; - } else { - self.write(format!("{value}").as_bytes())?; - } + let _ = self.write(rows.get_column_name(i).as_bytes()); } let _ = self.writeln(""); + headers_printed = true; } - Ok(StepResult::IO) => { - let start = Instant::now(); - rows.run_once()?; - if let Some(ref mut stats) = statistics { - stats.io_time_elapsed_samples.push(start.elapsed()); + + let row = rows.row().unwrap(); + for (i, value) in row.get_values().enumerate() { + if i > 0 { + let _ = self.write(b"|"); + } + if matches!(value, Value::Null) { + self.write_null()?; + } else { + write!(self, "{value}")?; } } - Ok(StepResult::Interrupt) => { - if let Some(ref mut stats) = statistics { - stats.execute_time_elapsed_samples.push(start.elapsed()); - } - break; - } - Ok(StepResult::Done) => { - if let Some(ref mut stats) = statistics { - stats.execute_time_elapsed_samples.push(start.elapsed()); - } - break; - } - Ok(StepResult::Busy) => { - if let Some(ref mut stats) = statistics { - stats.execute_time_elapsed_samples.push(start.elapsed()); - } - let _ = self.writeln("database is busy"); - break; - } - Err(err) => { - if let Some(ref mut stats) = statistics { - stats.execute_time_elapsed_samples.push(start.elapsed()); - } - let report = - miette::Error::from(err).with_source_code(sql.to_owned()); - let _ = self.write_fmt(format_args!("{report:?}")); - break; - } - } + let _ = self.writeln(""); + }); } } OutputMode::Pretty => { - if self.interrupt_count.load(Ordering::Acquire) > 0 { - println!("Query interrupted."); - return Ok(()); - } let config = self.config.as_ref().unwrap(); let mut table = Table::new(); table @@ -759,163 +767,69 @@ impl Limbo { table.set_header(header); } loop { - let start = Instant::now(); - match rows.step() { - Ok(StepResult::Row) => { - if let Some(ref mut stats) = statistics { - stats.execute_time_elapsed_samples.push(start.elapsed()); - } - let record = rows.row().unwrap(); - let mut row = Row::new(); - row.max_height(1); - for (idx, value) in record.get_values().enumerate() { - let (content, alignment) = match value { - Value::Null => { - (self.opts.null_value.clone(), CellAlignment::Left) - } - Value::Integer(_) => { - (format!("{value}"), CellAlignment::Right) - } - Value::Float(_) => { - (format!("{value}"), CellAlignment::Right) - } - Value::Text(_) => (format!("{value}"), CellAlignment::Left), - Value::Blob(_) => (format!("{value}"), CellAlignment::Left), - }; - row.add_cell( - Cell::new(content) - .set_alignment(alignment) - .fg(config.table.column_colors - [idx % config.table.column_colors.len()] - .as_comfy_table_color()), - ); - } - table.add_row(row); + row_step_result_query!(self, sql, rows, statistics, { + let record = rows.row().unwrap(); + let mut row = Row::new(); + row.max_height(1); + for (idx, value) in record.get_values().enumerate() { + let (content, alignment) = match value { + Value::Null => { + (self.opts.null_value.clone(), CellAlignment::Left) + } + Value::Integer(_) => (format!("{value}"), CellAlignment::Right), + Value::Float(_) => (format!("{value}"), CellAlignment::Right), + Value::Text(_) => (format!("{value}"), CellAlignment::Left), + Value::Blob(_) => (format!("{value}"), CellAlignment::Left), + }; + row.add_cell( + Cell::new(content) + .set_alignment(alignment) + .fg(config.table.column_colors + [idx % config.table.column_colors.len()] + .as_comfy_table_color()), + ); } - Ok(StepResult::IO) => { - let start = Instant::now(); - rows.run_once()?; - if let Some(ref mut stats) = statistics { - stats.io_time_elapsed_samples.push(start.elapsed()); - } - } - Ok(StepResult::Interrupt) => { - if let Some(ref mut stats) = statistics { - stats.execute_time_elapsed_samples.push(start.elapsed()); - } - break; - } - Ok(StepResult::Done) => { - if let Some(ref mut stats) = statistics { - stats.execute_time_elapsed_samples.push(start.elapsed()); - } - break; - } - Ok(StepResult::Busy) => { - if let Some(ref mut stats) = statistics { - stats.execute_time_elapsed_samples.push(start.elapsed()); - } - let _ = self.writeln("database is busy"); - break; - } - Err(err) => { - if let Some(ref mut stats) = statistics { - stats.execute_time_elapsed_samples.push(start.elapsed()); - } - let report = - miette::Error::from(err).with_source_code(sql.to_owned()); - let _ = self.write_fmt(format_args!("{report:?}")); - break; - } - } + table.add_row(row); + }); } if !table.is_empty() { - let _ = self.write_fmt(format_args!("{table}")); + write!(self, "{table}")?; } } OutputMode::Line => { let mut first_row_printed = false; + + let max_width = (0..rows.num_columns()) + .map(|i| rows.get_column_name(i).len()) + .max() + .unwrap_or(0); + + let formatted_columns: Vec = (0..rows.num_columns()) + .map(|i| format!("{:>width$}", rows.get_column_name(i), width = max_width)) + .collect(); + loop { - if self.interrupt_count.load(Ordering::Acquire) > 0 { - println!("Query interrupted."); - return Ok(()); - } + row_step_result_query!(self, sql, rows, statistics, { + let record = rows.row().unwrap(); - let start = Instant::now(); + if !first_row_printed { + first_row_printed = true; + } else { + self.writeln("")?; + } - let max_width = (0..rows.num_columns()) - .map(|i| rows.get_column_name(i).len()) - .max() - .unwrap_or(0); - - let formatted_columns: Vec = (0..rows.num_columns()) - .map(|i| { - format!("{:>width$}", rows.get_column_name(i), width = max_width) - }) - .collect(); - - match rows.step() { - Ok(StepResult::Row) => { - if let Some(ref mut stats) = statistics { - stats.execute_time_elapsed_samples.push(start.elapsed()); - } - let record = rows.row().unwrap(); - - if !first_row_printed { - first_row_printed = true; + for (i, value) in record.get_values().enumerate() { + self.write(&formatted_columns[i])?; + self.write(b" = ")?; + if matches!(value, Value::Null) { + self.write_null()?; } else { - self.writeln("")?; - } - - for (i, value) in record.get_values().enumerate() { - self.write(&formatted_columns[i])?; - self.write(b" = ")?; - if matches!(value, Value::Null) { - let bytes = self.opts.null_value.clone(); - self.write(bytes.as_bytes())?; - } else { - self.write(format!("{value}").as_bytes())?; - } - self.writeln("")?; + write!(self, "{value}")?; } + self.writeln("")?; } - Ok(StepResult::IO) => { - let start = Instant::now(); - rows.run_once()?; - if let Some(ref mut stats) = statistics { - stats.io_time_elapsed_samples.push(start.elapsed()); - } - } - Ok(StepResult::Interrupt) => { - if let Some(ref mut stats) = statistics { - stats.execute_time_elapsed_samples.push(start.elapsed()); - } - break; - } - Ok(StepResult::Done) => { - if let Some(ref mut stats) = statistics { - stats.execute_time_elapsed_samples.push(start.elapsed()); - } - break; - } - Ok(StepResult::Busy) => { - if let Some(ref mut stats) = statistics { - stats.execute_time_elapsed_samples.push(start.elapsed()); - } - let _ = self.writeln("database is busy"); - break; - } - Err(err) => { - if let Some(ref mut stats) = statistics { - stats.execute_time_elapsed_samples.push(start.elapsed()); - } - let report = - miette::Error::from(err).with_source_code(sql.to_owned()); - let _ = self.write_fmt(format_args!("{report:?}")); - break; - } - } + }); } } },