use quarb::QueryResult;
fn doc() -> quarb_json::JsonAdapter {
quarb_json::JsonAdapter::parse(r#"{"a":{"x":1,"y":"two","z":[1,2]},"r":{"t":"s"}}"#).unwrap()
}
fn rows(q: &str) -> Vec<String> {
match quarb::run(q, &doc()).unwrap_or_else(|e| panic!("{q}: {e}")) {
QueryResult::Values(vs) => vs.iter().map(|v| v.display_form()).collect(),
other => panic!("{q}: {other:?}"),
}
}
fn refuse(q: &str) -> String {
quarb::run(q, &doc()).unwrap_err().to_string()
}
#[test]
fn project_reads_projections_on_the_cursor() {
assert_eq!(rows("/a | project(:name)"), rows("/a | :name"));
assert_eq!(rows("/a | project(::z)"), ["@(1; 2)"]);
assert_eq!(rows("/a | project(:kind)"), ["object"]);
assert_eq!(rows("/a | project(@(:name; ::x; :kind))"), [r#"@("a"; 1; "object")"#]);
assert_eq!(
rows("/a | project(@(:name; ::x; :kind); -r)"),
[r#"%(name = "a"; x = 1; kind = "object")"#]
);
assert_eq!(rows("/a | project(:props)"), [r#"@(1; "two"; @(1; 2))"#]);
assert_eq!(rows("/a | project(:props; -r)"), rows("/a | %"));
assert_eq!(rows("/a | project(:meta; -r)"), [r#"%(type = "object"; length = 3)"#]);
assert_eq!(rows("/a | .p(:props) | project($.p; -r)"), rows("/a | %"));
let fields = rows("/a | project(:fields; -r) | keys");
assert!(fields[0].starts_with(r#"@("name"; "id"; "index""#), "{fields:?}");
assert_eq!(rows("/a | project((fields); -r)"), rows("/a | project(:fields; -r)"));
assert_eq!(rows("/a | % | project((fields); -r)"), rows("/a | %"));
assert_eq!(
rows(r#"= #(@(name; age); %("Braund"; 22)) | project((fields); -r) | keys"#),
[r#"@("name"; "age")"#]
);
assert_eq!(rows("/a | project((fields | [1]))"), ["a"]);
assert_eq!(rows("/a | project(fields)"), ["fields"]);
assert_eq!(rows("/a | % | project(:x)"), ["1"]);
assert_eq!(rows("/a | % | project(@(:x; :y); -r)"), [r#"%(x = 1; y = "two")"#]);
assert_eq!(rows("/a/* | project(:name)"), ["x", "y", "z"]);
assert_eq!(rows("/a | project(::nothing)"), [""]);
assert_eq!(rows("/a | project(@(:id; 1))"), [format!("@({}; 1)", rows("/a | :id")[0])]);
assert_eq!(
rows("/a | project(%(n = :name; k = :kind; fixed = 1))"),
[r#"%(n = "a"; k = "object"; fixed = 1)"#]
);
assert_eq!(
rows("/a | project(#(@(k; v); %(:name; 1); %(:kind; 2)))"),
["#(@(k; v);\n %(\"a\"; 1);\n %(\"object\"; 2))"]
);
assert_eq!(rows(r#"/a | project("::name")"#), ["::name"]);
assert_eq!(rows("/a | project(5)"), ["5"]);
assert_eq!(rows("/a | project(@(1; 2))"), ["@(1; 2)"]);
assert_eq!(
rows("/a | .p(:props) | project(%(all = $.p; first = ($.p | [1])))"),
[r#"%(all = @(1; "two"; @(1; 2)); first = 1)"#]
);
}
#[test]
fn project_refuses_what_is_no_projection() {
let e = refuse("/a | project(@(:name; ::name); -r)");
assert!(e.contains("share the bare key 'name' (:name and ::name)"), "{e}");
let e = refuse("/a | project(@(1; 2); -r)");
assert!(e.contains("item 1 of the list is no projection (1)"), "{e}");
let e = refuse("/a | project(%(n = :name); -r)");
assert!(e.contains("the record has its keys already"), "{e}");
let e = refuse("/a | project(fields; -r)");
assert!(e.contains("text is no list"), "{e}");
let e = refuse("/a | project(5; -r)");
assert!(e.contains("a number is no list"), "{e}");
let e = refuse("/a | project()");
assert!(e.contains("takes the value to read the projections of"), "{e}");
let e = refuse("/a | project(:name; -x)");
assert!(e.contains("--record"), "{e}");
}