1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
pub mod ast;
#[cfg(feature = "cli")]
mod cli;
mod error;
mod parser;
mod semantic;
mod sql;
mod utils;
pub use anyhow::Result;
pub use ast::display;
#[cfg(feature = "cli")]
pub use cli::Cli;
pub use error::{format_error, SourceLocation};
pub use parser::parse;
pub use semantic::*;
pub use sql::{resolve_and_translate, translate};
pub fn compile(prql: &str) -> Result<String> {
parse(prql).and_then(resolve_and_translate)
}
pub fn format(prql: &str) -> Result<String> {
parse(prql).map(display)
}
pub fn to_json(prql: &str) -> Result<String> {
Ok(serde_json::to_string(&parse(prql)?)?)
}
pub fn from_json(json: &str) -> Result<String> {
Ok(display(serde_json::from_str(json)?))
}
#[cfg(test)]
mod test {
use super::*;
use crate::to_json;
#[test]
fn test_to_json() -> Result<()> {
let json = to_json("from employees | take 10")?;
assert_eq!(json.chars().next().unwrap(), '{');
assert_eq!(json.chars().nth(json.len() - 1).unwrap(), '}');
Ok(())
}
#[test]
fn test_from_json() -> Result<()> {
let original_prql = r#"from employees
join salaries [emp_no]
group [emp_no, gender] (
aggregate [
emp_salary = average salary
]
)
join de=dept_emp [emp_no]
join dm=dept_manager [
(dm.dept_no == de.dept_no) and s"(de.from_date, de.to_date) OVERLAPS (dm.from_date, dm.to_date)"
]
group [dm.emp_no, gender] (
aggregate [
salary_avg = average emp_salary,
salary_sd = stddev emp_salary
]
)
derive mng_no = dm.emp_no
join managers=employees [emp_no]
derive mng_name = s"managers.first_name || ' ' || managers.last_name"
select [mng_name, managers.gender, salary_avg, salary_sd]"#;
let sql_from_prql = compile(original_prql)?;
let json = to_json(original_prql)?;
let prql_from_json = from_json(&json)?;
let sql_from_json = compile(&prql_from_json)?;
assert_eq!(sql_from_prql, sql_from_json);
Ok(())
}
}