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