use serde_json::{json, Map, Value};
use crate::command::T2Q_MAX_ROWS;
use crate::schema::{Profile, Registry};
pub(crate) fn param<'a>(params: &'a Map<String, Value>, r: Option<&String>) -> Option<&'a Value> {
let r = r?;
if r.is_empty() {
return None;
}
let key = r.get(1..).unwrap_or("");
params.get(key)
}
pub(crate) fn collect_having_agg_refs(
having: &Value,
is_agg: &dyn Fn(&str) -> bool,
out: &mut std::collections::HashSet<String>,
) {
let Some(m) = having.as_object() else {
return;
};
for (k, v) in m {
if matches!(k.as_str(), "$and" | "$or" | "$nor") {
if let Some(arr) = v.as_array() {
for it in arr {
collect_having_agg_refs(it, is_agg, out);
}
}
} else if !k.starts_with('$') && is_agg(k) {
out.insert(k.clone());
}
}
}
pub(crate) fn is_nullish(v: Option<&Value>) -> bool {
match v {
None => true,
Some(Value::Null) => true,
Some(_) => false,
}
}
pub(crate) fn non_nullish(v: Option<&Value>) -> Option<&Value> {
v.filter(|x| !x.is_null())
}
pub(crate) fn force_t2q_limit(registry: &Registry, limit: Option<&Value>) -> Option<Value> {
if registry.profile() != Profile::Text2Query {
return limit.cloned();
}
let l = limit.and_then(|v| v.as_f64()).unwrap_or(T2Q_MAX_ROWS);
Some(Value::from(l.min(T2Q_MAX_ROWS) as i64))
}
pub(crate) fn clamp_t2q_limit(registry: &Registry, limit: Option<&Value>) -> Option<Value> {
let v = limit?;
if registry.profile() != Profile::Text2Query {
return Some(v.clone());
}
match v.as_f64() {
Some(l) => Some(Value::from(l.min(T2Q_MAX_ROWS) as i64)),
None => Some(v.clone()),
}
}
pub(super) fn find_stage_idx(stages: &[Value], key: &str) -> Option<usize> {
stages
.iter()
.position(|s| s.as_object().map(|o| o.contains_key(key)).unwrap_or(false))
}
pub(super) fn append_order(
stages: &mut Vec<Value>,
sort: Option<&Value>,
skip_val: Option<&Value>,
limit_val: Option<&Value>,
) {
if let Some(v) = non_nullish(sort) {
stages.push(json!({ "$sort": v.clone() }));
}
if let Some(v) = non_nullish(skip_val) {
stages.push(json!({ "$skip": v.clone() }));
}
if let Some(v) = non_nullish(limit_val) {
stages.push(json!({ "$limit": v.clone() }));
}
}