iridium-db 0.3.0

A high-performance vector-graph hybrid storage and indexing engine
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, &params, &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);
        }
    }
}