use std::sync::Arc;
use hamelin_lib::catalog::{Catalog, CatalogProvider, Column};
use hamelin_lib::err::{ContextualTranslationErrors, WithTranslationErrors};
use hamelin_lib::provider::EnvironmentProvider;
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 struct CompileHamelinQueryResultOk {
pub columns: Vec<Column>,
}
#[derive(Serialize, Tsify)]
#[tsify(into_wasm_abi)]
pub enum CompileHamelinQueryResult {
Ok(CompileHamelinQueryResultOk),
Err(ContextualTranslationErrors),
}
#[wasm_bindgen]
pub fn compile_query(
query: String,
catalog: Catalog,
) -> Result<CompileHamelinQueryResult, JsValue> {
let catalog_provider = Arc::new(
CatalogProvider::try_from(catalog)
.map_err(|e| JsValue::from_str(e.to_string().as_str()))?,
);
Ok(compile_query_with_provider(query, catalog_provider))
}
pub fn compile_query_with_provider(
query: String,
provider: Arc<dyn EnvironmentProvider>,
) -> CompileHamelinQueryResult {
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), provider);
let mut errors = parse_errors;
errors.extend(semantic_errors);
if !errors.is_empty() {
return CompileHamelinQueryResult::Err(ContextualTranslationErrors::new(query, errors));
}
CompileHamelinQueryResult::Ok(CompileHamelinQueryResultOk {
columns: typed_statement.schema().into(),
})
}
#[derive(Serialize, Tsify)]
#[tsify(into_wasm_abi)]
pub enum QueryDatasetsResult {
Ok(Vec<String>),
Err(ContextualTranslationErrors),
}
#[wasm_bindgen]
pub fn get_statement_datasets(query: String) -> QueryDatasetsResult {
let (ast, errors) = Query::parse_with_errors(query.clone());
if !errors.is_empty() {
return QueryDatasetsResult::Err(ContextualTranslationErrors::new(query, errors));
}
match ast.datasets() {
Ok(datasets) => {
QueryDatasetsResult::Ok(datasets.into_iter().map(|id| id.to_string()).collect())
}
Err(error) => QueryDatasetsResult::Err(ContextualTranslationErrors::new(
query,
(*error).clone().single(),
)),
}
}