Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8730a828c6 | |||
| 776a442374 | |||
| 5c1779651c |
@ -38,7 +38,7 @@ pub struct Database {
|
||||
}
|
||||
|
||||
impl Database {
|
||||
pub fn new(val: &serde_json::Value) -> Result<Self, crate::drop::Drop> {
|
||||
pub fn new(val: &serde_json::Value) -> (Self, crate::drop::Drop) {
|
||||
let mut db = Self {
|
||||
enums: HashMap::new(),
|
||||
types: HashMap::new(),
|
||||
@ -151,10 +151,12 @@ impl Database {
|
||||
}
|
||||
|
||||
db.compile(&mut errors);
|
||||
if !errors.is_empty() {
|
||||
return Err(crate::drop::Drop::with_errors(errors));
|
||||
}
|
||||
Ok(db)
|
||||
let drop = if errors.is_empty() {
|
||||
crate::drop::Drop::success()
|
||||
} else {
|
||||
crate::drop::Drop::with_errors(errors)
|
||||
};
|
||||
(db, drop)
|
||||
}
|
||||
|
||||
/// Override the default executor for unit testing
|
||||
|
||||
@ -588,6 +588,8 @@ impl Schema {
|
||||
prop_name,
|
||||
Some(&keys_for_ambiguity),
|
||||
is_array,
|
||||
self.id.as_deref(),
|
||||
&format!("/{}", prop_name),
|
||||
errors,
|
||||
) {
|
||||
schema_edges.insert(
|
||||
@ -617,6 +619,8 @@ pub(crate) fn resolve_relation<'a>(
|
||||
prop_name: &str,
|
||||
relative_keys: Option<&Vec<String>>,
|
||||
is_array: bool,
|
||||
schema_id: Option<&str>,
|
||||
path: &str,
|
||||
errors: &mut Vec<crate::drop::Error>,
|
||||
) -> Option<(&'a crate::database::relation::Relation, bool)> {
|
||||
// Enforce graph locality by ensuring we don't accidentally crawl to pure structural entity boundaries
|
||||
@ -661,13 +665,21 @@ pub(crate) fn resolve_relation<'a>(
|
||||
|
||||
// Abort relation discovery early if no hierarchical inheritance match was found
|
||||
if matching_rels.is_empty() {
|
||||
let mut details = crate::drop::ErrorDetails {
|
||||
path: path.to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
if let Some(sid) = schema_id {
|
||||
details.schema = Some(sid.to_string());
|
||||
}
|
||||
|
||||
errors.push(crate::drop::Error {
|
||||
code: "EDGE_MISSING".to_string(),
|
||||
message: format!(
|
||||
"No database relation exists between '{}' and '{}' for property '{}'",
|
||||
parent_type, child_type, prop_name
|
||||
),
|
||||
details: crate::drop::ErrorDetails::default(),
|
||||
details,
|
||||
});
|
||||
return None;
|
||||
}
|
||||
@ -752,13 +764,21 @@ pub(crate) fn resolve_relation<'a>(
|
||||
// we must abort rather than silently guessing. Returning None prevents arbitrary SQL generation
|
||||
// and forces a clean structural error for the architect.
|
||||
if !resolved {
|
||||
let mut details = crate::drop::ErrorDetails {
|
||||
path: path.to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
if let Some(sid) = schema_id {
|
||||
details.schema = Some(sid.to_string());
|
||||
}
|
||||
|
||||
errors.push(crate::drop::Error {
|
||||
code: "AMBIGUOUS_TYPE_RELATIONS".to_string(),
|
||||
message: format!(
|
||||
"Ambiguous database relation between '{}' and '{}' for property '{}'",
|
||||
parent_type, child_type, prop_name
|
||||
),
|
||||
details: crate::drop::ErrorDetails::default(),
|
||||
details,
|
||||
});
|
||||
return None;
|
||||
}
|
||||
|
||||
19
src/jspg.rs
19
src/jspg.rs
@ -12,18 +12,21 @@ pub struct Jspg {
|
||||
}
|
||||
|
||||
impl Jspg {
|
||||
pub fn new(database_val: &serde_json::Value) -> Result<Self, crate::drop::Drop> {
|
||||
let database_instance = Database::new(database_val)?;
|
||||
pub fn new(database_val: &serde_json::Value) -> (Self, crate::drop::Drop) {
|
||||
let (database_instance, drop) = Database::new(database_val);
|
||||
let database = Arc::new(database_instance);
|
||||
let validator = Validator::new(database.clone());
|
||||
let queryer = Queryer::new(database.clone());
|
||||
let merger = Merger::new(database.clone());
|
||||
|
||||
Ok(Self {
|
||||
database,
|
||||
validator,
|
||||
queryer,
|
||||
merger,
|
||||
})
|
||||
(
|
||||
Self {
|
||||
database,
|
||||
validator,
|
||||
queryer,
|
||||
merger,
|
||||
},
|
||||
drop,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
21
src/lib.rs
21
src/lib.rs
@ -42,21 +42,16 @@ fn jspg_failure() -> JsonB {
|
||||
|
||||
#[cfg_attr(not(test), pg_extern(strict))]
|
||||
pub fn jspg_setup(database: JsonB) -> JsonB {
|
||||
match crate::jspg::Jspg::new(&database.0) {
|
||||
Ok(new_jspg) => {
|
||||
let new_arc = Arc::new(new_jspg);
|
||||
let (new_jspg, drop) = crate::jspg::Jspg::new(&database.0);
|
||||
let new_arc = Arc::new(new_jspg);
|
||||
|
||||
// 3. ATOMIC SWAP
|
||||
{
|
||||
let mut lock = GLOBAL_JSPG.write().unwrap();
|
||||
*lock = Some(new_arc);
|
||||
}
|
||||
|
||||
let drop = crate::drop::Drop::success();
|
||||
JsonB(serde_json::to_value(drop).unwrap())
|
||||
}
|
||||
Err(drop) => JsonB(serde_json::to_value(drop).unwrap()),
|
||||
// 3. ATOMIC SWAP
|
||||
{
|
||||
let mut lock = GLOBAL_JSPG.write().unwrap();
|
||||
*lock = Some(new_arc);
|
||||
}
|
||||
|
||||
JsonB(serde_json::to_value(drop).unwrap())
|
||||
}
|
||||
|
||||
#[cfg_attr(not(test), pg_extern)]
|
||||
|
||||
@ -42,10 +42,11 @@ fn get_cached_file(path: &str) -> CompiledSuite {
|
||||
|
||||
let mut compiled_suites = Vec::new();
|
||||
for suite in suites {
|
||||
let db_result = crate::database::Database::new(&suite.database);
|
||||
let compiled_db = match db_result {
|
||||
Ok(db) => Ok(Arc::new(db)),
|
||||
Err(drop) => Err(drop),
|
||||
let (db, drop) = crate::database::Database::new(&suite.database);
|
||||
let compiled_db = if drop.errors.is_empty() {
|
||||
Ok(Arc::new(db))
|
||||
} else {
|
||||
Err(drop)
|
||||
};
|
||||
compiled_suites.push((suite, Arc::new(compiled_db)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user