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