use super::{Ast, BitmapPredicate, ProjectionItem, VectorPredicate, WhereClause};
pub(super) fn ast_to_json_pretty(ast: &Ast) -> String {
let predicate = ast
.where_predicate
.as_ref()
.map(vector_predicate_json)
.unwrap_or_else(|| "null".to_string());
let bitmap_predicate = ast
.where_bitmap_predicate
.as_ref()
.map(bitmap_predicate_json)
.unwrap_or_else(|| "null".to_string());
let where_clause = ast
.where_clause
.as_ref()
.map(where_clause_json)
.unwrap_or_else(|| "null".to_string());
let with_items = projections_json(&ast.with_items);
let return_items = projections_json(&ast.return_items);
let match_aliases = ast
.match_aliases
.iter()
.map(|alias| format!("\"{}\"", alias))
.collect::<Vec<_>>()
.join(", ");
let limit = ast
.limit
.map(|v| v.to_string())
.unwrap_or_else(|| "null".to_string());
format!(
concat!(
"{{\n",
" \"match\": {{ \"aliases\": [{}], \"primary_alias\": \"{}\" }},\n",
" \"where\": {},\n",
" \"where_vector\": {},\n",
" \"where_bitmap\": {},\n",
" \"with\": [{}],\n",
" \"return\": {{ \"items\": [{}], \"primary_alias\": \"{}\" }},\n",
" \"limit\": {}\n",
"}}\n"
),
match_aliases,
ast.match_alias,
where_clause,
predicate,
bitmap_predicate,
with_items,
return_items,
ast.return_alias,
limit
)
}
fn projections_json(items: &[ProjectionItem]) -> String {
items
.iter()
.map(|item| match item {
ProjectionItem::Identifier(value) => format!("\"{}\"", value),
ProjectionItem::Function {
name,
argument,
alias,
} => {
if let Some(alias) = alias {
format!(
"{{\"function\":\"{}\",\"argument\":\"{}\",\"alias\":\"{}\"}}",
name, argument, alias
)
} else {
format!(
"{{\"function\":\"{}\",\"argument\":\"{}\",\"alias\":null}}",
name, argument
)
}
}
})
.collect::<Vec<_>>()
.join(", ")
}
fn vector_predicate_json(pred: &VectorPredicate) -> String {
format!(
concat!(
"{{\n",
" \"function\": \"{}\",\n",
" \"target\": \"{}\",\n",
" \"param\": \"{}\",\n",
" \"operator\": \"{}\",\n",
" \"threshold\": \"{}\"\n",
" }}"
),
pred.function, pred.target, pred.param, pred.operator, pred.threshold
)
}
fn bitmap_predicate_json(pred: &BitmapPredicate) -> String {
format!(
concat!(
"{{\n",
" \"function\": \"{}\",\n",
" \"index_name\": \"{}\",\n",
" \"value_key\": \"{}\"\n",
" }}"
),
pred.function, pred.index_name, pred.value_key
)
}
fn where_clause_json(where_clause: &WhereClause) -> String {
match where_clause {
WhereClause::Function {
function,
args,
operator,
threshold,
} => format!(
"{{\"kind\":\"function\",\"function\":\"{}\",\"args\":[{}],\"operator\":\"{}\",\"threshold\":\"{}\"}}",
function,
args.iter()
.map(|arg| format!("\"{}\"", arg))
.collect::<Vec<_>>()
.join(", "),
operator,
threshold
),
WhereClause::Comparison {
left,
operator,
right,
} => format!(
"{{\"kind\":\"comparison\",\"left\":\"{}\",\"operator\":\"{}\",\"right\":\"{}\"}}",
left, operator, right
),
}
}