use std::sync::Arc;
use hamelin_analysis::incremental::detect_supported_strategies_for_query;
use hamelin_lib::catalog::{Catalog, CatalogProvider};
use hamelin_lib::err::{ContextualTranslationErrors, WithTranslationErrors};
use hamelin_lib::tree::ast::query::Query;
use hamelin_lib::tree::ast::ParseWithErrors;
use hamelin_lib::type_check_with_provider;
use serde::Serialize;
use tsify::Tsify;
use wasm_bindgen::prelude::wasm_bindgen;
use wasm_bindgen::JsValue;
#[derive(Serialize, Tsify)]
#[tsify(into_wasm_abi)]
pub enum IncrementalEligibilityResult {
Eligible { strategies: Vec<String> },
NotEligible { reasons: Vec<String> },
CompilationError(ContextualTranslationErrors),
}
#[wasm_bindgen]
pub fn check_incremental_eligibility(
query: String,
catalog: Catalog,
allow_lookups: bool,
) -> Result<IncrementalEligibilityResult, JsValue> {
let catalog_provider = Arc::new(
CatalogProvider::try_from(catalog)
.map_err(|e| JsValue::from_str(e.to_string().as_str()))?,
);
let (ast, parse_errors) = Query::parse_with_errors(query.clone());
let WithTranslationErrors {
output: typed_statement,
errors: semantic_errors,
} = type_check_with_provider::<Query>(Arc::new(ast), catalog_provider);
let mut errors = parse_errors;
errors.extend(semantic_errors);
if !errors.is_empty() {
return Ok(IncrementalEligibilityResult::CompilationError(
ContextualTranslationErrors::new(query, errors),
));
}
let result = detect_supported_strategies_for_query(&typed_statement, allow_lookups);
if result.supported.is_empty() {
Ok(IncrementalEligibilityResult::NotEligible {
reasons: result.rejections,
})
} else {
Ok(IncrementalEligibilityResult::Eligible {
strategies: result
.supported
.into_iter()
.map(|s| format!("{s:?}"))
.collect(),
})
}
}