use insta::assert_snapshot;
use super::sql::compile;
#[test]
fn test_errors() {
assert_snapshot!(compile(r###"
let addadd = a b -> a + b
from x
derive y = (addadd 4 5 6)
"###).unwrap_err(),
@r"
Error:
╭─[ :5:17 ]
│
5 │ derive y = (addadd 4 5 6)
│ ──────┬─────
│ ╰─────── Too many arguments to function `addadd`
───╯
");
assert_snapshot!(compile(r###"
from a select b
"###).unwrap_err(),
@r"
Error:
╭─[ :2:5 ]
│
2 │ from a select b
│ ───────┬───────
│ ╰───────── Too many arguments to function `from`
───╯
");
assert_snapshot!(compile(r###"
from x
select a
select b
"###).unwrap_err(),
@r"
Error:
╭─[ :4:12 ]
│
4 │ select b
│ ┬
│ ╰── Unknown name `b`
│
│ Help: available columns: x.a
───╯
");
assert_snapshot!(compile(r###"
from employees
take 1.8
"###).unwrap_err(),
@r"
Error:
╭─[ :3:10 ]
│
3 │ take 1.8
│ ─┬─
│ ╰─── `take` expected int or range, but found 1.8
───╯
");
use insta::assert_debug_snapshot;
let mississippi = "Mississippi has four S’s and four I’s.";
assert_debug_snapshot!(prqlc_parser::lexer::lex_source(mississippi).unwrap_err(), @r#"
[
Error {
kind: Error,
span: Some(
0:22-23,
),
reason: Unexpected {
found: "'’'",
},
hints: [],
code: None,
},
]
"#);
assert_snapshot!(compile(mississippi).unwrap_err(), @r"
Error:
╭─[ :1:23 ]
│
1 │ Mississippi has four S’s and four I’s.
│ ┬
│ ╰── unexpected '’'
───╯
");
assert_snapshot!(compile("Answer: T-H-A-T!").unwrap_err(), @r"
Error:
╭─[ :1:16 ]
│
1 │ Answer: T-H-A-T!
│ ┬
│ ╰── expected something else, but found !
───╯
");
}
#[test]
fn test_union_all_sqlite() {
assert_snapshot!(compile(r###"
prql target:sql.sqlite
from film
remove film2
"###).unwrap_err(), @r"
Error: The dialect SQLiteDialect does not support EXCEPT ALL
↳ Hint: providing more column information will allow the query to be translated to an anti-join.
")
}
#[test]
fn test_regex_dialect() {
assert_snapshot!(compile(r###"
prql target:sql.mssql
from foo
filter bar ~= 'love'
"###).unwrap_err(), @r"
Error:
╭─[ :4:12 ]
│
4 │ filter bar ~= 'love'
│ ──────┬──────
│ ╰──────── operator std.regex_search is not supported for dialect mssql
───╯
")
}
#[test]
fn test_bad_function_type() {
assert_snapshot!(compile(r###"
from tracks
group foo (take)
"###,
)
.unwrap_err(), @r"
Error:
╭─[ :3:16 ]
│
3 │ group foo (take)
│ ──┬─
│ ╰─── function std.group, param `pipeline` expected type `transform`, but found type `func ? relation -> relation`
│
│ Help: Type `transform` expands to `func relation -> relation`
───╯
");
}
#[test]
#[ignore]
fn test_basic_type_checking() {
assert_snapshot!(compile(r#"
from foo
select (a && b) + c
"#)
.unwrap_err(), @r###"
Error:
╭─[:3:13]
│
3 │ select (a && b) + c
│ ───┬──
│ ╰──── function std.add, param `left` expected type `int || float || timestamp || date`, but found type `bool`
───╯
"###);
}
#[test]
fn test_ambiguous() {
assert_snapshot!(compile(r#"
from a
derive date = x
select date
"#)
.unwrap_err(), @r"
Error:
╭─[ :4:12 ]
│
4 │ select date
│ ──┬─
│ ╰─── Ambiguous name
│
│ Help: could be any of: std.date, this.date
│
│ Note: available columns: date
───╯
");
}
#[test]
fn test_ambiguous_join() {
assert_snapshot!(compile(r#"
from a
select x
join (from b | select {x}) true
select x
"#)
.unwrap_err(), @r"
Error:
╭─[ :5:12 ]
│
5 │ select x
│ ┬
│ ╰── Ambiguous name
│
│ Help: could be any of: a.x, b.x
│
│ Note: available columns: a.x, b.x
───╯
");
}
#[test]
fn test_ambiguous_inference() {
assert_snapshot!(compile(r#"
from a
join b(==b_id)
select x
"#)
.unwrap_err(), @r"
Error:
╭─[ :4:12 ]
│
4 │ select x
│ ┬
│ ╰── Ambiguous name
│
│ Help: could be any of: a.x, b.x
───╯
");
}
#[test]
fn date_to_text_generic() {
assert_snapshot!(compile(r#"
[{d = @2021-01-01}]
derive {
d_str = (d | date.to_text "%Y/%m/%d")
}"#).unwrap_err(), @r#"
Error:
╭─[ :4:31 ]
│
4 │ d_str = (d | date.to_text "%Y/%m/%d")
│ ─────┬────
│ ╰────── Date formatting requires a dialect
───╯
"#);
}
#[test]
fn date_to_text_with_column_format() {
assert_snapshot!(compile(r#"
from dates_to_display
select {my_date, my_format}
select {std.date.to_text my_date my_format}
"#).unwrap_err(), @r"
Error:
╭─[ :4:11 ]
│
4 │ select {std.date.to_text my_date my_format}
│ ─────────────────┬────────────────
│ ╰────────────────── `std.date.to_text` only supports a string literal as format
───╯
");
}
#[test]
fn date_to_text_unsupported_chrono_item() {
assert_snapshot!(compile(r#"
prql target:sql.duckdb
from [{d = @2021-01-01}]
derive {
d_str = (d | date.to_text "%_j")
}"#).unwrap_err(), @r#"
Error:
╭─[ :6:33 ]
│
6 │ d_str = (d | date.to_text "%_j")
│ ──┬──
│ ╰──── PRQL doesn't support this format specifier
───╯
"#);
}
#[test]
fn available_columns() {
assert_snapshot!(compile(r#"
from invoices
select foo
select bar
"#).unwrap_err(), @r"
Error:
╭─[ :4:12 ]
│
4 │ select bar
│ ─┬─
│ ╰─── Unknown name `bar`
│
│ Help: available columns: invoices.foo
───╯
");
}
#[test]
fn empty_interpolations() {
assert_snapshot!(compile(r#"from x | select f"{}" "#).unwrap_err(), @r#"
Error:
╭─[ :1:20 ]
│
1 │ from x | select f"{}"
│ ┬
│ ╰── expected interpolated string variable or '{', but found "}"
───╯
"#);
}
#[test]
fn no_query_entered() {
assert_snapshot!(compile("").unwrap_err(), @r"
[E0001] Error: No PRQL query entered
");
assert_snapshot!(compile("# just a comment").unwrap_err(), @r"
[E0001] Error: No PRQL query entered
");
}
#[test]
fn query_must_begin_with_from() {
assert_snapshot!(compile("let x = 5").unwrap_err(), @r"
[E0001] Error: PRQL queries must begin with 'from'
↳ Hint: A query must start with a 'from' statement to define the main pipeline
");
assert_snapshot!(compile(r#"
let x = 5
let y = 10
"#).unwrap_err(), @r"
[E0001] Error: PRQL queries must begin with 'from'
↳ Hint: A query must start with a 'from' statement to define the main pipeline
");
}
#[test]
fn negative_number_in_transform() {
assert_snapshot!(compile(r###"
from artists
sort -name
"###).unwrap_err(), @r"
Error: expected a pipeline that resolves to a table, but found `internal std.sub`
↳ Hint: wrap negative numbers in parentheses, e.g. `sort (-column_name)`
");
assert_snapshot!(compile(r###"
from pets
take -10
"###).unwrap_err(), @r"
Error: expected a pipeline that resolves to a table, but found `internal std.sub`
↳ Hint: wrap negative numbers in parentheses, e.g. `sort (-column_name)`
");
assert_snapshot!(compile(r###"
from tbl
group id (
sort -val
)
"###).unwrap_err(), @r"
Error: expected a pipeline that resolves to a table, but found `internal std.sub`
↳ Hint: wrap negative numbers in parentheses, e.g. `sort (-column_name)`
");
}
#[test]
fn empty_tuple_or_array_from() {
assert_snapshot!(compile(r###"
from {}
"###).unwrap_err(), @r"
Error:
╭─[ :2:10 ]
│
2 │ from {}
│ ─┬
│ ╰── expected a table or query, but found an empty tuple `{}`
───╯
");
assert_snapshot!(compile(r###"
from []
"###).unwrap_err(), @r"
Error:
╭─[ :2:10 ]
│
2 │ from []
│ ─┬
│ ╰── expected a table or query, but found an empty array `[]`
───╯
");
assert_snapshot!(compile(r###"
from {}
select a
"###).unwrap_err(), @r"
Error:
╭─[ :2:10 ]
│
2 │ from {}
│ ─┬
│ ╰── expected a table or query, but found an empty tuple `{}`
───╯
");
}
#[test]
fn window_rows_expects_range() {
assert_snapshot!(compile(r###"
from t
group sid (window rows:2 (sid))
"###).unwrap_err(), @r"
Error:
╭─[ :3:28 ]
│
3 │ group sid (window rows:2 (sid))
│ ┬
│ ╰── parameter `rows` expected a range, but found 2
───╯
");
assert_snapshot!(compile(r###"
from t
group sid (window range:2 (sid))
"###).unwrap_err(), @r"
Error:
╭─[ :3:29 ]
│
3 │ group sid (window range:2 (sid))
│ ┬
│ ╰── parameter `range` expected a range, but found 2
───╯
");
}
#[test]
fn bare_lambda_expression() {
assert_snapshot!(compile(r###"
x -> y
"###).unwrap_err(), @r"
Error:
╭─[ :2:5 ]
│
2 │ x -> y
│ ───┬──
│ ╰──── expected a table, but found a function
───╯
");
}