use grafeo_engine::GrafeoDB;
fn db() -> GrafeoDB {
GrafeoDB::new_in_memory()
}
#[test]
fn create_schema_enables_default_graph() {
let db = db();
let s = db.session();
s.execute("CREATE SCHEMA reporting").unwrap();
s.execute("SESSION SET SCHEMA reporting").unwrap();
s.execute("INSERT (:Report {title: 'Q1'})").unwrap();
let result = s.execute("MATCH (n:Report) RETURN n.title").unwrap();
assert_eq!(result.row_count(), 1);
}
#[test]
fn schema_default_isolated_from_global() {
let db = db();
let s = db.session();
s.execute("INSERT (:Global {v: 1})").unwrap();
s.execute("CREATE SCHEMA s1").unwrap();
s.execute("SESSION SET SCHEMA s1").unwrap();
s.execute("INSERT (:Local {v: 2})").unwrap();
let result = s.execute("MATCH (n) RETURN n").unwrap();
assert_eq!(result.row_count(), 1, "schema should only see its own data");
s.execute("SESSION RESET SCHEMA").unwrap();
let result = s.execute("MATCH (n) RETURN n").unwrap();
assert_eq!(
result.row_count(),
1,
"global default should only see its own data"
);
}
#[test]
fn named_graph_within_schema() {
let db = db();
let s = db.session();
s.execute("CREATE SCHEMA reports").unwrap();
s.execute("SESSION SET SCHEMA reports").unwrap();
s.execute("CREATE GRAPH quarterly").unwrap();
s.execute("SESSION SET GRAPH quarterly").unwrap();
s.execute("INSERT (:Report {q: 1})").unwrap();
s.execute("SESSION RESET GRAPH").unwrap();
let result = s.execute("MATCH (n:Report) RETURN n").unwrap();
assert_eq!(
result.row_count(),
0,
"schema default should not see data from named graph"
);
s.execute("SESSION SET GRAPH quarterly").unwrap();
let result = s.execute("MATCH (n:Report) RETURN n").unwrap();
assert_eq!(result.row_count(), 1);
}
#[test]
fn show_graphs_filters_and_hides_default() {
let db = db();
let s = db.session();
s.execute("CREATE SCHEMA s1").unwrap();
s.execute("SESSION SET SCHEMA s1").unwrap();
s.execute("CREATE GRAPH alpha").unwrap();
s.execute("CREATE GRAPH beta").unwrap();
let result = s.execute("SHOW GRAPHS").unwrap();
assert_eq!(result.row_count(), 2, "__default__ should be hidden");
s.execute("SESSION RESET SCHEMA").unwrap();
let result = s.execute("SHOW GRAPHS").unwrap();
assert_eq!(
result.row_count(),
0,
"global scope should not see schema-scoped graphs"
);
}
#[test]
fn cross_schema_data_isolation() {
let db = db();
let s = db.session();
s.execute("CREATE SCHEMA a").unwrap();
s.execute("CREATE SCHEMA b").unwrap();
s.execute("SESSION SET SCHEMA a").unwrap();
s.execute("INSERT (:Item {from: 'a'})").unwrap();
s.execute("SESSION SET SCHEMA b").unwrap();
let result = s.execute("MATCH (n) RETURN n").unwrap();
assert_eq!(
result.row_count(),
0,
"schema b should not see schema a data"
);
s.execute("SESSION SET SCHEMA a").unwrap();
let result = s.execute("MATCH (n) RETURN n").unwrap();
assert_eq!(result.row_count(), 1);
}
#[test]
fn drop_schema_blocks_when_user_graphs_exist() {
let db = db();
let s = db.session();
s.execute("CREATE SCHEMA s1").unwrap();
s.execute("SESSION SET SCHEMA s1").unwrap();
s.execute("CREATE GRAPH myg").unwrap();
s.execute("SESSION RESET SCHEMA").unwrap();
let result = s.execute("DROP SCHEMA s1");
assert!(
result.is_err(),
"should fail: schema has user-created graphs"
);
}
#[test]
fn drop_schema_succeeds_with_only_default_graph() {
let db = db();
let s = db.session();
s.execute("CREATE SCHEMA s1").unwrap();
s.execute("DROP SCHEMA s1").unwrap();
let result = s.execute("SHOW SCHEMAS").unwrap();
assert_eq!(result.row_count(), 0, "schema should be gone");
}
#[test]
fn drop_schema_resets_session_if_active() {
let db = db();
let s = db.session();
s.execute("CREATE SCHEMA temp").unwrap();
s.execute("SESSION SET SCHEMA temp").unwrap();
s.execute("DROP SCHEMA temp").unwrap();
assert!(
s.current_schema().is_none(),
"dropping active schema should reset session"
);
}
#[test]
fn setting_schema_does_not_reset_graph() {
let db = db();
let s = db.session();
s.execute("CREATE GRAPH standalone").unwrap();
s.execute("SESSION SET GRAPH standalone").unwrap();
s.execute("CREATE SCHEMA s1").unwrap();
s.execute("SESSION SET SCHEMA s1").unwrap();
assert_eq!(s.current_graph(), Some("standalone".to_string()));
}
#[test]
fn setting_graph_does_not_reset_schema() {
let db = db();
let s = db.session();
s.execute("CREATE SCHEMA s1").unwrap();
s.execute("SESSION SET SCHEMA s1").unwrap();
s.execute("CREATE GRAPH myg").unwrap();
s.execute("SESSION SET GRAPH myg").unwrap();
assert_eq!(s.current_schema(), Some("s1".to_string()));
}
#[test]
fn reset_schema_independent_of_graph() {
let db = db();
let s = db.session();
s.execute("CREATE SCHEMA s1").unwrap();
s.execute("SESSION SET SCHEMA s1").unwrap();
s.execute("CREATE GRAPH myg").unwrap();
s.execute("SESSION SET GRAPH myg").unwrap();
s.execute("SESSION RESET SCHEMA").unwrap();
assert!(s.current_schema().is_none());
assert_eq!(s.current_graph(), Some("myg".to_string()));
}
#[test]
fn reset_graph_independent_of_schema() {
let db = db();
let s = db.session();
s.execute("CREATE SCHEMA s1").unwrap();
s.execute("SESSION SET SCHEMA s1").unwrap();
s.execute("CREATE GRAPH myg").unwrap();
s.execute("SESSION SET GRAPH myg").unwrap();
s.execute("SESSION RESET GRAPH").unwrap();
assert_eq!(s.current_schema(), Some("s1".to_string()));
assert!(s.current_graph().is_none());
}
#[test]
fn create_schema_rejects_slash_in_name() {
let db = db();
let s = db.session();
let result = s.execute("CREATE SCHEMA `foo/bar`");
assert!(
result.is_err(),
"CREATE SCHEMA with '/' in name should fail (reserved separator)"
);
}
#[test]
fn create_graph_rejects_slash_in_name() {
let db = db();
let s = db.session();
let result = s.execute("CREATE GRAPH `foo/bar`");
assert!(
result.is_err(),
"CREATE GRAPH with '/' in name should fail (reserved separator)"
);
}
#[test]
fn no_schema_backward_compat() {
let db = db();
let s = db.session();
s.execute("INSERT (:Person {name: 'Alix'})").unwrap();
s.execute("CREATE GRAPH g1").unwrap();
s.execute("USE GRAPH g1").unwrap();
s.execute("INSERT (:Event {type: 'click'})").unwrap();
s.execute("USE GRAPH default").unwrap();
let result = s.execute("MATCH (n:Person) RETURN n").unwrap();
assert_eq!(result.row_count(), 1, "default graph should still work");
}