use turso_pg_parser::parse;
#[test]
fn test_invalid_syntax() {
let queries = vec![
"SELECT * FORM users", "SELECT * FROM", "SELECT * FROM users WHERE", "INSERT INTO users", "UPDATE users", "DELETE users", "CREATE TABLE", "DROP", ];
for sql in queries {
assert!(parse(sql).is_err(), "Should have failed to parse: {sql}");
}
}
#[test]
fn test_invalid_dollar_parameters() {
let queries = vec![
"SELECT * FROM users WHERE id = $", "SELECT * FROM users WHERE id = $abc", "SELECT * FROM users WHERE id = $-1", ];
for sql in queries {
assert!(parse(sql).is_err(), "Should have failed to parse: {sql}");
}
}
#[test]
fn test_unterminated_strings() {
let queries = vec![
"SELECT 'unterminated",
"SELECT \"unterminated identifier",
"SELECT $tag$unterminated dollar quote",
"SELECT $$unterminated",
];
for sql in queries {
assert!(parse(sql).is_err(), "Should have failed to parse: {sql}");
}
}
#[test]
fn test_mismatched_parentheses() {
let queries = vec![
"SELECT * FROM users WHERE (id = 1",
"SELECT * FROM users WHERE id = 1)",
"INSERT INTO users (name, email VALUES ('test', 'test@example.com')",
"CREATE TABLE users (id INTEGER",
"SELECT ARRAY[1, 2, 3",
"SELECT func(1, 2",
];
for sql in queries {
assert!(parse(sql).is_err(), "Should have failed to parse: {sql}");
}
}
#[test]
fn test_invalid_type_casts() {
let queries = vec![
"SELECT 'test':", "SELECT 'test'::", "SELECT ::integer", ];
for sql in queries {
assert!(parse(sql).is_err(), "Should have failed to parse: {sql}");
}
}
#[test]
fn test_invalid_json_operators() {
let queries = vec![
"SELECT data->", "SELECT data#>", "SELECT ->>'field' FROM table", ];
for sql in queries {
assert!(parse(sql).is_err(), "Should have failed to parse: {sql}");
}
}
#[test]
fn test_invalid_on_conflict() {
let queries = vec![
"INSERT INTO users VALUES (1) ON CONFLICT", "INSERT INTO users VALUES (1) ON CONFLICT DO", "INSERT INTO users VALUES (1) ON CONFLICT (email)", "INSERT INTO users VALUES (1) ON CONFLICT DO SOMETHING", ];
for sql in queries {
assert!(parse(sql).is_err(), "Should have failed to parse: {sql}");
}
}
#[test]
fn test_invalid_window_functions() {
let queries = vec![
"SELECT ROW_NUMBER() OVER", "SELECT ROW_NUMBER() OVER (", "SELECT ROW_NUMBER() OVER (PARTITION)", "SELECT ROW_NUMBER() OVER (ORDER)", ];
for sql in queries {
assert!(parse(sql).is_err(), "Should have failed to parse: {sql}");
}
}
#[test]
fn test_invalid_cte() {
let queries = vec![
"WITH AS (SELECT * FROM users) SELECT * FROM cte", "WITH cte SELECT * FROM cte", "WITH cte AS SELECT * FROM users", "WITH cte AS () SELECT * FROM cte", ];
for sql in queries {
assert!(parse(sql).is_err(), "Should have failed to parse: {sql}");
}
}
#[test]
fn test_invalid_case() {
let queries = vec![
"SELECT CASE WHEN true THEN 1", "SELECT CASE WHEN true 1 END", "SELECT CASE true THEN 1 END", "SELECT CASE status WHEN THEN 1 END", ];
for sql in queries {
assert!(parse(sql).is_err(), "Should have failed to parse: {sql}");
}
}
#[test]
fn test_invalid_create_table() {
let queries = vec![
"CREATE TABLE users", "CREATE TABLE users (id INTEGER,)", ];
for sql in queries {
assert!(parse(sql).is_err(), "Should have failed to parse: {sql}");
}
}
#[test]
fn test_invalid_nulls_ordering() {
let queries = vec![
"SELECT * FROM users ORDER BY name NULLS", "SELECT * FROM users ORDER BY name NULLS MIDDLE", ];
for sql in queries {
assert!(parse(sql).is_err(), "Should have failed to parse: {sql}");
}
}
#[test]
fn test_sqlite_specific_syntax() {
let queries = vec![
"ATTACH DATABASE 'file.db' AS other",
"CREATE VIRTUAL TABLE ft USING fts5(content)",
"PRAGMA table_info(users)",
"CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT)", "SELECT * FROM users LIMIT 10 OFFSET 20", ];
for sql in queries {
println!("Testing SQLite-specific syntax: {sql}");
let result = parse(sql);
if result.is_err() {
println!(" -> Correctly rejected SQLite syntax");
} else {
println!(" -> Accepted (may need stricter validation)");
}
}
}
#[test]
fn test_missing_statement_features() {
let queries = vec![
"\\getenv var value", "COPY users FROM :'variable'", "\\set var value", "\\d users", ];
for sql in queries {
assert!(
parse(sql).is_err(),
"Should fail to parse psql command: {sql}"
);
}
}
#[test]
fn test_complex_invalid_syntax() {
let queries = vec![
"SELECT max(row(a,b)) FROM", "array(select sum(x+y) s", "SELECT '{1,2,3}'::int[", "CREATE TEMPORARY TABLE (", ];
for sql in queries {
assert!(
parse(sql).is_err(),
"Should fail to parse invalid syntax: {sql}"
);
}
}
#[test]
fn test_postgresql_unsupported_admin_commands() {
let queries = vec![
"VACUUM",
"REINDEX TABLE users",
"CLUSTER users USING users_idx",
"CHECKPOINT",
"LOAD 'extension'",
];
for sql in queries {
let result = parse(sql);
{
let status = if result.is_ok() { "OK" } else { "FAIL" };
println!("Testing admin command: {sql} -> {status}");
}
}
}
#[test]
fn test_invalid_operators() {
let queries = vec![
"SELECT array @>", ];
for sql in queries {
assert!(
parse(sql).is_err(),
"Should fail to parse invalid operator: {sql}"
);
}
}