json_eval_rs/parse_schema/
common.rs1use crate::jsoneval::path_utils;
2use crate::jsoneval::table_metadata::ColumnMetadata;
3use indexmap::IndexSet;
5use serde_json::Value;
6
7pub fn collect_refs(value: &Value, refs: &mut IndexSet<String>) {
9 match value {
10 Value::Object(map) => {
11 if let Some(path) = map.get("$ref").and_then(Value::as_str) {
12 refs.insert(path_utils::normalize_to_json_pointer(path));
13 }
14 if let Some(path) = map.get("ref").and_then(Value::as_str) {
15 refs.insert(path_utils::normalize_to_json_pointer(path));
16 }
17 if let Some(var_val) = map.get("var") {
18 match var_val {
19 Value::String(s) => {
20 refs.insert(s.clone());
21 }
22 Value::Array(arr) => {
23 if let Some(path) = arr.get(0).and_then(Value::as_str) {
24 refs.insert(path.to_string());
25 }
26 }
27 _ => {}
28 }
29 }
30 for val in map.values() {
31 collect_refs(val, refs);
32 }
33 }
34 Value::Array(arr) => {
35 for val in arr {
36 collect_refs(val, refs);
37 }
38 }
39 _ => {}
40 }
41}
42
43pub fn compute_column_partitions(columns: &[ColumnMetadata]) -> (Vec<usize>, Vec<usize>) {
48 use std::collections::HashSet;
49
50 let mut fwd_cols = HashSet::new();
52 for col in columns {
53 if col.has_forward_ref {
54 fwd_cols.insert(col.name.as_ref());
55 }
56 }
57
58 loop {
60 let mut changed = false;
61 for col in columns {
62 if !fwd_cols.contains(col.name.as_ref()) {
63 for dep in col.dependencies.iter() {
65 let dep_name = dep.trim_start_matches('$');
67 if fwd_cols.contains(dep_name) {
68 fwd_cols.insert(col.name.as_ref());
69 changed = true;
70 break;
71 }
72 }
73 }
74 }
75 if !changed {
77 break;
78 }
79 }
80
81 let mut forward_indices = Vec::new();
83 let mut normal_indices = Vec::new();
84
85 for (idx, col) in columns.iter().enumerate() {
86 if fwd_cols.contains(col.name.as_ref()) {
87 forward_indices.push(idx);
88 } else {
89 normal_indices.push(idx);
90 }
91 }
92
93 (forward_indices, normal_indices)
94}