• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

getdozer / dozer / 5608958238

pending completion
5608958238

push

github

web-flow
fix: Fix config combination with separated sql scripts (#1773)

* fix: Fix config combination with seperated sql scripts

* add more tests

* Refactor sql changes

* Refactor error

97 of 97 new or added lines in 2 files covered. (100.0%)

42214 of 54451 relevant lines covered (77.53%)

34646.24 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

26.09
/dozer-sql/src/jsonpath/parser/parser.rs
1
use crate::jsonpath::parser::model::FilterExpression::{And, Or};
2
use crate::jsonpath::parser::model::{
3
    FilterExpression, FilterSign, Function, JsonPath, JsonPathIndex, Operand,
4
};
5
use dozer_types::json_types::JsonValue;
6
use pest::error::Error;
7
use pest::iterators::{Pair, Pairs};
8
use pest::Parser;
9

10
#[derive(Parser)]
2,905✔
11
#[grammar = "jsonpath/parser/grammar/json_path.pest"]
12
pub struct JsonPathParser;
13

14
/// the parsing function.
15
/// Since the parsing can finish with error the result is [[Result]]
16
#[allow(clippy::result_large_err)]
17
pub fn parse_json_path(jp_str: &str) -> Result<JsonPath, Error<Rule>> {
15✔
18
    Ok(parse_internal(
15✔
19
        JsonPathParser::parse(Rule::path, jp_str)?.next().unwrap(),
15✔
20
    ))
21
}
15✔
22

23
/// Internal function takes care of the logic by parsing the operators and unrolling the string into the final result.
24
fn parse_internal(rule: Pair<Rule>) -> JsonPath {
71✔
25
    match rule.as_rule() {
71✔
26
        Rule::path => rule
15✔
27
            .into_inner()
15✔
28
            .next()
15✔
29
            .map(parse_internal)
15✔
30
            .unwrap_or(JsonPath::Empty),
15✔
31
        Rule::current => JsonPath::Current(Box::new(
×
32
            rule.into_inner()
×
33
                .next()
×
34
                .map(parse_internal)
×
35
                .unwrap_or(JsonPath::Empty),
×
36
        )),
×
37
        Rule::chain => JsonPath::Chain(rule.into_inner().map(parse_internal).collect()),
15✔
38
        Rule::root => JsonPath::Root,
13✔
39
        Rule::wildcard => JsonPath::Wildcard,
1✔
40
        Rule::descent => parse_key(down(rule))
×
41
            .map(JsonPath::Descent)
×
42
            .unwrap_or(JsonPath::Empty),
×
43
        Rule::descent_w => JsonPath::DescentW,
1✔
44
        Rule::function => JsonPath::Fn(Function::Length),
×
45
        Rule::field => parse_key(down(rule))
20✔
46
            .map(JsonPath::Field)
20✔
47
            .unwrap_or(JsonPath::Empty),
20✔
48
        Rule::index => JsonPath::Index(parse_index(rule)),
6✔
49
        _ => JsonPath::Empty,
×
50
    }
51
}
71✔
52

53
/// parsing the rule 'key' with the structures either .key or .]'key'[
54
fn parse_key(rule: Pair<Rule>) -> Option<String> {
20✔
55
    match rule.as_rule() {
20✔
56
        Rule::key | Rule::key_unlim | Rule::string_qt => parse_key(down(rule)),
×
57
        Rule::key_lim | Rule::inner => Some(String::from(rule.as_str())),
20✔
58
        _ => None,
×
59
    }
60
}
20✔
61

62
fn parse_slice(mut pairs: Pairs<Rule>) -> JsonPathIndex {
×
63
    let mut start = 0;
×
64
    let mut end = 0;
×
65
    let mut step = 1;
×
66
    while pairs.peek().is_some() {
×
67
        let in_pair = pairs.next().unwrap();
×
68
        match in_pair.as_rule() {
×
69
            Rule::start_slice => start = in_pair.as_str().parse::<i32>().unwrap_or(start),
×
70
            Rule::end_slice => end = in_pair.as_str().parse::<i32>().unwrap_or(end),
×
71
            Rule::step_slice => step = down(in_pair).as_str().parse::<usize>().unwrap_or(step),
×
72
            _ => (),
×
73
        }
74
    }
75
    JsonPathIndex::Slice(start, end, step)
×
76
}
×
77

78
fn parse_unit_keys(mut pairs: Pairs<Rule>) -> JsonPathIndex {
×
79
    let mut keys = vec![];
×
80

81
    while pairs.peek().is_some() {
×
82
        keys.push(String::from(down(pairs.next().unwrap()).as_str()));
×
83
    }
×
84
    JsonPathIndex::UnionKeys(keys)
×
85
}
×
86

87
fn number_to_value(number: &str) -> JsonValue {
6✔
88
    number.parse::<f64>().ok().map(JsonValue::from).unwrap()
6✔
89
}
6✔
90

91
fn parse_unit_indexes(mut pairs: Pairs<Rule>) -> JsonPathIndex {
×
92
    let mut keys = vec![];
×
93

94
    while pairs.peek().is_some() {
×
95
        keys.push(number_to_value(pairs.next().unwrap().as_str()));
×
96
    }
×
97
    JsonPathIndex::UnionIndex(keys)
×
98
}
×
99

100
fn parse_chain_in_operand(rule: Pair<Rule>) -> Operand {
×
101
    match parse_internal(rule) {
×
102
        JsonPath::Chain(elems) => {
×
103
            if elems.len() == 1 {
×
104
                match elems.first() {
×
105
                    Some(JsonPath::Index(JsonPathIndex::UnionKeys(keys))) => {
×
106
                        Operand::val(JsonValue::from(keys.clone()))
×
107
                    }
108
                    Some(JsonPath::Index(JsonPathIndex::UnionIndex(keys))) => {
×
109
                        Operand::val(JsonValue::from(keys.clone()))
×
110
                    }
111
                    Some(JsonPath::Field(f)) => {
×
112
                        Operand::val(JsonValue::Array(vec![JsonValue::from(f.clone())]))
×
113
                    }
114
                    _ => Operand::Dynamic(Box::new(JsonPath::Chain(elems))),
×
115
                }
116
            } else {
117
                Operand::Dynamic(Box::new(JsonPath::Chain(elems)))
×
118
            }
119
        }
120
        jp => Operand::Dynamic(Box::new(jp)),
×
121
    }
122
}
×
123

124
fn parse_filter_index(pair: Pair<Rule>) -> JsonPathIndex {
×
125
    JsonPathIndex::Filter(parse_logic(pair.into_inner()))
×
126
}
×
127

128
fn parse_logic(mut pairs: Pairs<Rule>) -> FilterExpression {
×
129
    let mut expr: Option<FilterExpression> = None;
×
130
    while pairs.peek().is_some() {
×
131
        let next_expr = parse_logic_and(pairs.next().unwrap().into_inner());
×
132
        match expr {
×
133
            None => expr = Some(next_expr),
×
134
            Some(e) => expr = Some(Or(Box::new(e), Box::new(next_expr))),
×
135
        }
136
    }
137
    expr.unwrap()
×
138
}
×
139

140
fn parse_logic_and(mut pairs: Pairs<Rule>) -> FilterExpression {
×
141
    let mut expr: Option<FilterExpression> = None;
×
142

143
    while pairs.peek().is_some() {
×
144
        let next_expr = parse_logic_atom(pairs.next().unwrap().into_inner());
×
145
        match expr {
×
146
            None => expr = Some(next_expr),
×
147
            Some(e) => expr = Some(And(Box::new(e), Box::new(next_expr))),
×
148
        }
149
    }
150
    expr.unwrap()
×
151
}
×
152

153
fn parse_logic_atom(mut pairs: Pairs<Rule>) -> FilterExpression {
×
154
    match pairs.peek().map(|x| x.as_rule()) {
×
155
        Some(Rule::logic) => parse_logic(pairs.next().unwrap().into_inner()),
×
156
        Some(Rule::atom) => {
157
            let left: Operand = parse_atom(pairs.next().unwrap());
×
158
            if pairs.peek().is_none() {
×
159
                FilterExpression::exists(left)
×
160
            } else {
161
                let sign: FilterSign = FilterSign::new(pairs.next().unwrap().as_str());
×
162
                let right: Operand = parse_atom(pairs.next().unwrap());
×
163
                FilterExpression::Atom(left, sign, right)
×
164
            }
165
        }
166
        Some(x) => panic!("unexpected => {:?}", x),
×
167
        None => panic!("unexpected none"),
×
168
    }
169
}
×
170

171
fn parse_atom(rule: Pair<Rule>) -> Operand {
×
172
    let atom = down(rule.clone());
×
173
    match atom.as_rule() {
×
174
        Rule::number => Operand::Static(number_to_value(rule.as_str())),
×
175
        Rule::string_qt => Operand::Static(JsonValue::from(down(atom).as_str())),
×
176
        Rule::chain => parse_chain_in_operand(down(rule)),
×
177
        Rule::boolean => Operand::Static(rule.as_str().parse().unwrap()),
×
178
        _ => Operand::Static(JsonValue::Null),
×
179
    }
180
}
×
181

182
fn parse_index(rule: Pair<Rule>) -> JsonPathIndex {
6✔
183
    let next = down(rule);
6✔
184
    match next.as_rule() {
6✔
185
        Rule::unsigned => JsonPathIndex::Single(number_to_value(next.as_str())),
6✔
186
        Rule::slice => parse_slice(next.into_inner()),
×
187
        Rule::unit_indexes => parse_unit_indexes(next.into_inner()),
×
188
        Rule::unit_keys => parse_unit_keys(next.into_inner()),
×
189
        Rule::filter => parse_filter_index(down(next)),
×
190
        _ => JsonPathIndex::Single(number_to_value(next.as_str())),
×
191
    }
192
}
6✔
193

194
fn down(rule: Pair<Rule>) -> Pair<Rule> {
26✔
195
    rule.into_inner().next().unwrap()
26✔
196
}
26✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc