From 6f5a96fa499616db89eddc81fc20964758047648 Mon Sep 17 00:00:00 2001 From: zgq Date: Sun, 20 Sep 2026 18:05:44 +0800 Subject: [PATCH] Exit quietly when the reader closes stdout --- crates/cli/src/main.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 0a09bbd..806ad01 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -7,7 +7,7 @@ use serde_json::{json, Value}; use sqlx_protocol::{Action, Connection, Database}; use std::{ collections::BTreeMap, - io::{self, IsTerminal}, + io::{self, IsTerminal, Write}, path::PathBuf, }; use storage::{Datasource, Store}; @@ -236,9 +236,8 @@ fn main() { Ok(true) => {} Ok(false) => std::process::exit(1), Err(e) => { - println!( - "{}", - json!({"success":false,"error":{"code":e.downcast_ref::().map(|e| e.code.as_str()).unwrap_or("sqlx.error"),"message":format!("{e:#}")}}) + print_line( + &json!({"success":false,"error":{"code":e.downcast_ref::().map(|e| e.code.as_str()).unwrap_or("sqlx.error"),"message":format!("{e:#}")}}), ); std::process::exit(1); } @@ -543,8 +542,19 @@ fn run(cli: Cli) -> Result { } Ok(true) } +/// Write one JSON line. A consumer that stops reading (`sqlx … | head`) must not turn +/// into a panic; any other write failure still reports itself and fails. +fn print_line(value: &Value) { + if let Err(error) = writeln!(io::stdout(), "{value}") { + if error.kind() == io::ErrorKind::BrokenPipe { + std::process::exit(0); + } + eprintln!("sqlx could not write its result: {error}"); + std::process::exit(1); + } +} fn print(data: Value) { - println!("{}", json!({"success":true,"data":data})); + print_line(&json!({"success":true,"data":data})); } fn validate_name(name: &str) -> Result<()> { if name.trim().is_empty() || uuid::Uuid::parse_str(name).is_ok() {