use std::path::Path;
use iridium::features::ops;
use iridium::features::query;
use iridium::features::runtime;
use iridium::features::storage::api;
use super::common::{env_u64_or, env_usize_or, open_store_with_data_root};
pub(super) fn run_query_command(query_str: &str, data_root: Option<&Path>) {
let ast = match query::parse(query_str) {
Ok(ast) => ast,
Err(err) => {
ops::record_query_error();
eprintln!("query parse failed: {:?}", err);
std::process::exit(1);
}
};
let typed = match query::validate(&ast, &query::Catalog) {
Ok(typed) => typed,
Err(err) => {
ops::record_query_error();
eprintln!("query validation failed: {:?}", err);
std::process::exit(1);
}
};
let plan = match runtime::explain(&typed) {
Ok(plan) => plan,
Err(err) => {
ops::record_query_error();
eprintln!("query planning failed: {:?}", err);
std::process::exit(1);
}
};
let mut handle = match open_store_with_data_root(data_root) {
Ok(handle) => handle,
Err(err) => {
eprintln!("failed to open store: {:?}", err);
std::process::exit(1);
}
};
if let Err(err) = api::recover_from_wal(&mut handle) {
eprintln!("query recovery failed: {:?}", err);
std::process::exit(1);
}
let scan_limit_multiplier = env_u64_or("IR_QUERY_SCAN_LIMIT_MULTIPLIER", 64).max(1);
let scan_min = env_u64_or("IR_QUERY_SCAN_MIN", 512).max(1);
let morsel_size = env_usize_or("IR_QUERY_MORSEL_SIZE", 256).max(1);
let parallel_workers = env_usize_or("IR_QUERY_PARALLEL_WORKERS", 0);
let scan_end = plan
.limit
.map(|limit| (limit.saturating_mul(scan_limit_multiplier)).max(scan_min))
.unwrap_or(4096_u64.max(scan_min));
let params = runtime::ExecuteParams {
scan_start: 0,
scan_end_exclusive: scan_end,
morsel_size,
parallel_workers,
};
match runtime::execute(&plan, ¶ms, &mut handle) {
Ok(rows) => {
ops::record_query_success(rows.latency_micros);
print!("{}", rows.to_json_pretty());
}
Err(err) => {
ops::record_query_error();
eprintln!("query execution failed: {:?}", err);
std::process::exit(1);
}
}
}