nodedb_query/window/
helpers.rs1use std::collections::HashMap;
6
7pub(super) fn build_partitions(
9 rows: &[(String, serde_json::Value)],
10 partition_by: &[String],
11) -> Vec<Vec<usize>> {
12 if partition_by.is_empty() {
13 return vec![(0..rows.len()).collect()];
14 }
15
16 let mut groups: HashMap<String, Vec<usize>> = HashMap::new();
17 let mut order = Vec::new();
18
19 for (i, (_id, doc)) in rows.iter().enumerate() {
20 let key: String = partition_by
24 .iter()
25 .map(|col| {
26 doc.get(col)
27 .map(|v| v.to_string())
28 .unwrap_or_else(|| "null".to_string())
29 })
30 .collect::<Vec<_>>()
31 .join("\x00");
32 let entry = groups.entry(key.clone()).or_default();
33 if entry.is_empty() {
34 order.push(key);
35 }
36 entry.push(i);
37 }
38
39 order.iter().filter_map(|k| groups.remove(k)).collect()
40}
41
42pub(super) fn set_window_col(row: &mut serde_json::Value, alias: &str, val: serde_json::Value) {
43 if let serde_json::Value::Object(map) = row {
44 map.insert(alias.to_string(), val);
45 }
46}
47
48pub(super) fn get_field(doc: &serde_json::Value, field: &str) -> serde_json::Value {
49 doc.get(field).cloned().unwrap_or(serde_json::Value::Null)
50}
51
52pub(super) fn as_f64(v: &serde_json::Value) -> Option<f64> {
53 match v {
54 serde_json::Value::Number(n) => n.as_f64(),
55 serde_json::Value::String(s) => s.parse().ok(),
56 _ => None,
57 }
58}
59
60pub(super) fn order_keys_equal(
63 rows: &[(String, serde_json::Value)],
64 a: usize,
65 b: usize,
66 order_by: &[(String, bool)],
67) -> bool {
68 order_by
69 .iter()
70 .all(|(col, _)| get_field(&rows[a].1, col) == get_field(&rows[b].1, col))
71}