mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-08-04 10:08:20 +00:00
fix: ctrl-c stop current query execution
This commit is contained in:
parent
e890a1d64f
commit
38a1b85094
3 changed files with 85 additions and 7 deletions
31
Cargo.lock
generated
31
Cargo.lock
generated
|
@ -220,6 +220,12 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.2.1"
|
||||
|
@ -490,6 +496,16 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctrlc"
|
||||
version = "3.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345"
|
||||
dependencies = [
|
||||
"nix 0.28.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "debugid"
|
||||
version = "0.8.0"
|
||||
|
@ -1014,6 +1030,7 @@ dependencies = [
|
|||
"anyhow",
|
||||
"clap 4.5.8",
|
||||
"cli-table",
|
||||
"ctrlc",
|
||||
"dirs",
|
||||
"env_logger 0.10.2",
|
||||
"limbo_core",
|
||||
|
@ -1149,6 +1166,18 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases 0.1.1",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.29.0"
|
||||
|
@ -1157,7 +1186,7 @@ checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
|
|||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"cfg_aliases 0.2.1",
|
||||
"libc",
|
||||
]
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ dist = true
|
|||
name = "limbo"
|
||||
path = "main.rs"
|
||||
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.75"
|
||||
clap = { version = "4.4.0", features = ["derive"] }
|
||||
|
@ -25,3 +26,4 @@ dirs = "5.0.1"
|
|||
env_logger = "0.10.1"
|
||||
limbo_core = { path = "../core" }
|
||||
rustyline = "12.0.0"
|
||||
ctrlc = "3.4.4"
|
59
cli/main.rs
59
cli/main.rs
|
@ -6,6 +6,7 @@ use limbo_core::{Database, RowResult, Value};
|
|||
use opcodes_dictionary::OPCODE_DESCRIPTIONS;
|
||||
use rustyline::{error::ReadlineError, DefaultEditor};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(ValueEnum, Copy, Clone, Debug, PartialEq, Eq)]
|
||||
|
@ -39,11 +40,24 @@ fn main() -> anyhow::Result<()> {
|
|||
let io = Arc::new(limbo_core::PlatformIO::new()?);
|
||||
let db = Database::open_file(io.clone(), path)?;
|
||||
let conn = db.connect();
|
||||
|
||||
let interrupt_count = Arc::new(AtomicUsize::new(0));
|
||||
|
||||
{
|
||||
let interrupt_count = Arc::clone(&interrupt_count);
|
||||
|
||||
ctrlc::set_handler(move || {
|
||||
// Increment the interrupt count on Ctrl-C
|
||||
interrupt_count.fetch_add(1, Ordering::SeqCst);
|
||||
})
|
||||
.expect("Error setting Ctrl-C handler");
|
||||
}
|
||||
|
||||
if let Some(sql) = opts.sql {
|
||||
if sql.trim().starts_with('.') {
|
||||
handle_dot_command(io.clone(), &conn, &sql)?;
|
||||
} else {
|
||||
query(io.clone(), &conn, &sql, &opts.output_mode)?;
|
||||
query(io.clone(), &conn, &sql, &opts.output_mode, &interrupt_count)?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -60,14 +74,27 @@ fn main() -> anyhow::Result<()> {
|
|||
match readline {
|
||||
Ok(line) => {
|
||||
rl.add_history_entry(line.to_owned())?;
|
||||
interrupt_count.store(0, Ordering::SeqCst);
|
||||
if line.trim().starts_with('.') {
|
||||
handle_dot_command(io.clone(), &conn, &line)?;
|
||||
} else {
|
||||
query(io.clone(), &conn, &line, &opts.output_mode)?;
|
||||
query(
|
||||
io.clone(),
|
||||
&conn,
|
||||
&line,
|
||||
&opts.output_mode,
|
||||
&interrupt_count,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
Err(ReadlineError::Interrupted) => {
|
||||
break;
|
||||
// At prompt, increment interrupt count
|
||||
if interrupt_count.fetch_add(1, Ordering::SeqCst) >= 1 {
|
||||
eprintln!("Interrupted. Exiting...");
|
||||
break;
|
||||
}
|
||||
println!("Use .quit to exit or press Ctrl-C again to force quit.");
|
||||
continue;
|
||||
}
|
||||
Err(ReadlineError::Eof) => {
|
||||
break;
|
||||
|
@ -91,16 +118,20 @@ In addition to standard SQL commands, the following special commands are availab
|
|||
|
||||
Special Commands:
|
||||
-----------------
|
||||
.quit Stop interpreting input stream and exit.
|
||||
.schema <table_name> Show the schema of the specified table.
|
||||
.opcodes Display all the opcodes defined by the virtual machine
|
||||
.help Display this help message.
|
||||
|
||||
Usage Examples:
|
||||
---------------
|
||||
1. To view the schema of a table named 'employees':
|
||||
1. To quit the Limbo SQL Shell:
|
||||
.quit
|
||||
|
||||
2. To view the schema of a table named 'employees':
|
||||
.schema employees
|
||||
|
||||
2. To list all available SQL opcodes:
|
||||
3. To list all available SQL opcodes:
|
||||
.opcodes
|
||||
|
||||
Note:
|
||||
|
@ -125,6 +156,10 @@ fn handle_dot_command(
|
|||
}
|
||||
|
||||
match args[0] {
|
||||
".quit" => {
|
||||
println!("Exiting Limbo SQL Shell.");
|
||||
std::process::exit(0)
|
||||
}
|
||||
".schema" => {
|
||||
let table_name = args.get(1).copied();
|
||||
display_schema(io, conn, table_name)?;
|
||||
|
@ -218,10 +253,16 @@ fn query(
|
|||
conn: &limbo_core::Connection,
|
||||
sql: &str,
|
||||
output_mode: &OutputMode,
|
||||
interrupt_count: &Arc<AtomicUsize>,
|
||||
) -> anyhow::Result<()> {
|
||||
match conn.query(sql) {
|
||||
Ok(Some(ref mut rows)) => match output_mode {
|
||||
OutputMode::Raw => loop {
|
||||
if interrupt_count.load(Ordering::SeqCst) > 0 {
|
||||
println!("Query interrupted.");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
match rows.next_row()? {
|
||||
RowResult::Row(row) => {
|
||||
for (i, value) in row.values.iter().enumerate() {
|
||||
|
@ -241,10 +282,16 @@ fn query(
|
|||
RowResult::IO => {
|
||||
io.run_once()?;
|
||||
}
|
||||
RowResult::Done => break,
|
||||
RowResult::Done => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
OutputMode::Pretty => {
|
||||
if interrupt_count.load(Ordering::SeqCst) > 0 {
|
||||
println!("Query interrupted.");
|
||||
return Ok(());
|
||||
}
|
||||
let mut table_rows: Vec<Vec<_>> = vec![];
|
||||
loop {
|
||||
match rows.next_row()? {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue