use surrealdb_types::ToSql;
use crate::syn::{expr, parse};
pub fn ensure_formats(s: &str) {
let parsed = crate::syn::parse(s).unwrap();
let parsed_formated = crate::syn::parse(&parsed.to_sql()).unwrap();
let plan: crate::expr::LogicalPlan = parsed.clone().into();
let parsed_formated_plan = crate::syn::parse(&plan.to_sql()).unwrap();
assert_eq!(parsed, parsed_formated, "formatting the sql type changed the query");
assert_eq!(parsed, parsed_formated_plan, "formatting the expr type changed the query");
}
macro_rules! test_case {
($name:ident => $source:literal) => {
#[test]
fn $name() {
ensure_formats($source)
}
};
}
test_case!(idiom_after_select => "(SELECT foo FROM bar ORDER BY foo)[0]");
test_case!(idiom_after_create => "(CREATE foo:1 SET V = $a)[0]");
test_case!(idiom_after_closure => "(|$a: number| { $a })[0]");
test_case!(covered_expr => "(1 + 1) * 3");
test_case!(idiom_after_idiom_index => "RETURN ([{ a: [1] }, { a: [2] }].a)[0]");
test_case!(idiom_after_idiom_method => "RETURN ([{ a: [1] }, { a: [2] }].a).len()");
test_case!(idiom_after_param_idiom => "RETURN ($x.a)[0]");
test_case!(idiom_stored_in_field_value => "DEFINE FIELD v ON t VALUE ([{ a: [1] }].a)[0]");
test_case!(idiom_stored_in_permission => "DEFINE TABLE t PERMISSIONS FOR select WHERE ([{ a: [1] }].a)[0] = 1");
test_case!(table_permissions_delete_full => "DEFINE TABLE t PERMISSIONS FOR select, delete FULL");
test_case!(table_permissions_delete_only => "DEFINE TABLE t PERMISSIONS FOR delete FULL");
test_case!(table_permissions_mixed => "DEFINE TABLE t PERMISSIONS FOR select FULL, FOR create, update, delete NONE");
test_case!(alter_table_permissions_delete_full => "ALTER TABLE t PERMISSIONS FOR select, delete FULL");
test_case!(field_permissions_mixed => "DEFINE FIELD f ON t PERMISSIONS FOR select FULL, FOR create, update NONE");
test_case!(field_permissions_none => "DEFINE FIELD f ON t PERMISSIONS NONE");
test_case!(alter_field_permissions_none => "ALTER FIELD f ON t PERMISSIONS NONE");
test_case!(alter_access_duration_token => "ALTER ACCESS a ON DATABASE DURATION FOR TOKEN 2h");
test_case!(alter_access_duration_grant => "ALTER ACCESS a ON DATABASE DURATION FOR GRANT 1d");
test_case!(alter_access_duration_all => "ALTER ACCESS a ON DATABASE DURATION FOR GRANT 1d, FOR TOKEN 2h, FOR SESSION 3h");
test_case!(alter_access_duration_drop => "ALTER ACCESS a ON DATABASE DURATION FOR GRANT NONE, FOR SESSION NONE");
test_case!(select_tempfiles => "SELECT * FROM t TEMPFILES");
test_case!(select_tempfiles_ordered => "SELECT * FROM t FOR UPDATE TEMPFILES EXPLAIN");
test_case!(remove_database_expunge => "REMOVE DATABASE AND EXPUNGE d");
test_case!(remove_namespace_expunge => "REMOVE NAMESPACE AND EXPUNGE IF EXISTS n");
test_case!(remove_table_expunge => "REMOVE TABLE AND EXPUNGE t");
#[test]
fn bearer_access_does_not_render_its_key() {
let query = parse(
"DEFINE ACCESS a ON DATABASE TYPE BEARER FOR USER WITH JWT ALGORITHM HS512 KEY 'topsecret'",
)
.unwrap();
let text = query.to_sql();
assert!(!text.contains("topsecret"), "a bearer access rendered its signing key: {text}");
assert!(!text.contains("WITH JWT"), "a bearer access rendered a JWT clause: {text}");
}
#[test]
fn access_without_type_is_database_only() {
parse("DEFINE ACCESS a ON DATABASE").unwrap();
parse("DEFINE ACCESS a ON ROOT").unwrap_err();
parse("DEFINE ACCESS a ON NAMESPACE").unwrap_err();
}
#[test]
fn pretty_query() {
let query = parse("SELECT * FROM {foo: [1, 2, 3]};").unwrap();
assert_eq!(query.to_sql(), "SELECT * FROM { foo: [1, 2, 3] };");
assert_eq!(query.to_sql_pretty(), "SELECT * FROM {\n\tfoo: [\n\t\t1,\n\t\t2,\n\t\t3\n\t]\n};");
}
#[test]
fn pretty_define_query() {
let query = parse("DEFINE TABLE test SCHEMAFULL PERMISSIONS FOR create, update, delete NONE FOR select WHERE public = true;").unwrap();
assert_eq!(
query.to_sql(),
"DEFINE TABLE test TYPE NORMAL SCHEMAFULL PERMISSIONS FOR select WHERE public = true, FOR create, update, delete NONE;"
);
assert_eq!(
query.to_sql_pretty(),
"DEFINE TABLE test TYPE NORMAL SCHEMAFULL\n\tPERMISSIONS\n\tFOR select WHERE public = true,\n\tFOR create, update, delete NONE;"
);
}
#[test]
fn pretty_value() {
let value = expr("{foo: [1, 2, 3]}").unwrap();
assert_eq!(value.to_sql(), "{ foo: [1, 2, 3] }");
assert_eq!(value.to_sql_pretty(), "{\n\tfoo: [\n\t\t1,\n\t\t2,\n\t\t3\n\t]\n}");
}
#[test]
fn pretty_array() {
let array = expr("[1, 2, 3]").unwrap();
assert_eq!(array.to_sql(), "[1, 2, 3]");
assert_eq!(array.to_sql_pretty(), "[\n\t1,\n\t2,\n\t3\n]");
}