merger now requires a schema id, queryer and merger now use pre-compiled edges for O(1) relations
This commit is contained in:
@ -1,3 +1,4 @@
|
||||
pub mod edge;
|
||||
pub mod r#enum;
|
||||
pub mod executors;
|
||||
pub mod formats;
|
||||
@ -23,14 +24,13 @@ use relation::Relation;
|
||||
use schema::Schema;
|
||||
use serde_json::Value;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
use r#type::Type;
|
||||
|
||||
pub struct Database {
|
||||
pub enums: HashMap<String, Enum>,
|
||||
pub types: HashMap<String, Type>,
|
||||
pub puncs: HashMap<String, Punc>,
|
||||
pub relations: Vec<Relation>,
|
||||
pub relations: HashMap<String, Relation>,
|
||||
pub schemas: HashMap<String, Schema>,
|
||||
pub descendants: HashMap<String, Vec<String>>,
|
||||
pub depths: HashMap<String, usize>,
|
||||
@ -42,7 +42,7 @@ impl Database {
|
||||
let mut db = Self {
|
||||
enums: HashMap::new(),
|
||||
types: HashMap::new(),
|
||||
relations: Vec::new(),
|
||||
relations: HashMap::new(),
|
||||
puncs: HashMap::new(),
|
||||
schemas: HashMap::new(),
|
||||
descendants: HashMap::new(),
|
||||
@ -76,7 +76,7 @@ impl Database {
|
||||
if db.types.contains_key(&def.source_type)
|
||||
&& db.types.contains_key(&def.destination_type)
|
||||
{
|
||||
db.relations.push(def);
|
||||
db.relations.insert(def.constraint.clone(), def);
|
||||
}
|
||||
}
|
||||
Err(e) => println!("DATABASE RELATION PARSE FAILED: {:?}", e),
|
||||
@ -140,7 +140,12 @@ impl Database {
|
||||
self.collect_schemas();
|
||||
self.collect_depths();
|
||||
self.collect_descendants();
|
||||
self.compile_schemas();
|
||||
|
||||
// Mathematically evaluate all property inheritances, formats, schemas, and foreign key edges topographically over OnceLocks
|
||||
let mut visited = std::collections::HashSet::new();
|
||||
for schema in self.schemas.values() {
|
||||
schema.compile(self, &mut visited);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -223,7 +228,7 @@ impl Database {
|
||||
self.descendants = descendants;
|
||||
}
|
||||
|
||||
pub fn get_relation(
|
||||
fn resolve_relation(
|
||||
&self,
|
||||
parent_type: &str,
|
||||
child_type: &str,
|
||||
@ -240,7 +245,7 @@ impl Database {
|
||||
let mut matching_rels = Vec::new();
|
||||
let mut directions = Vec::new();
|
||||
|
||||
for rel in &self.relations {
|
||||
for rel in self.relations.values() {
|
||||
let is_forward = p_def.hierarchy.contains(&rel.source_type)
|
||||
&& c_def.hierarchy.contains(&rel.destination_type);
|
||||
let is_reverse = p_def.hierarchy.contains(&rel.destination_type)
|
||||
@ -269,7 +274,10 @@ impl Database {
|
||||
// Reduce ambiguity with prefix
|
||||
for (i, rel) in matching_rels.iter().enumerate() {
|
||||
if let Some(prefix) = &rel.prefix {
|
||||
if prefix == prop_name {
|
||||
if prop_name.starts_with(prefix)
|
||||
|| prefix.starts_with(prop_name)
|
||||
|| prefix.replace("_", "") == prop_name.replace("_", "")
|
||||
{
|
||||
chosen_idx = i;
|
||||
resolved = true;
|
||||
break;
|
||||
@ -298,8 +306,8 @@ impl Database {
|
||||
|
||||
fn collect_descendants_recursively(
|
||||
target: &str,
|
||||
direct_refs: &HashMap<String, Vec<String>>,
|
||||
descendants: &mut HashSet<String>,
|
||||
direct_refs: &std::collections::HashMap<String, Vec<String>>,
|
||||
descendants: &mut std::collections::HashSet<String>,
|
||||
) {
|
||||
if let Some(children) = direct_refs.get(target) {
|
||||
for child in children {
|
||||
@ -309,86 +317,4 @@ impl Database {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_schemas(&mut self) {
|
||||
let schema_ids: Vec<String> = self.schemas.keys().cloned().collect();
|
||||
let mut compiled_names_map: HashMap<String, Vec<String>> = HashMap::new();
|
||||
let mut compiled_props_map: HashMap<String, std::collections::BTreeMap<String, Arc<Schema>>> =
|
||||
HashMap::new();
|
||||
|
||||
for id in &schema_ids {
|
||||
if let Some(schema) = self.schemas.get(id) {
|
||||
let mut visited = HashSet::new();
|
||||
let merged = self.merged_properties(schema, &mut visited);
|
||||
let mut names: Vec<String> = merged.keys().cloned().collect();
|
||||
if !names.is_empty() {
|
||||
names.sort();
|
||||
compiled_names_map.insert(id.clone(), names);
|
||||
compiled_props_map.insert(id.clone(), merged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for id in schema_ids {
|
||||
if let Some(schema) = self.schemas.get_mut(&id) {
|
||||
if let Some(names) = compiled_names_map.remove(&id) {
|
||||
schema.obj.compiled_property_names = Some(names);
|
||||
}
|
||||
if let Some(props) = compiled_props_map.remove(&id) {
|
||||
schema.obj.compiled_properties = Some(props);
|
||||
}
|
||||
schema.compile_internals();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn merged_properties(
|
||||
&self,
|
||||
schema: &Schema,
|
||||
visited: &mut HashSet<String>,
|
||||
) -> std::collections::BTreeMap<String, Arc<Schema>> {
|
||||
if let Some(props) = &schema.obj.compiled_properties {
|
||||
return props.clone();
|
||||
}
|
||||
|
||||
let mut props = std::collections::BTreeMap::new();
|
||||
|
||||
if let Some(id) = &schema.obj.id {
|
||||
if !visited.insert(id.clone()) {
|
||||
return props;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref_id) = &schema.obj.r#ref {
|
||||
if let Some(parent_schema) = self.schemas.get(ref_id) {
|
||||
props.extend(self.merged_properties(parent_schema, visited));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(all_of) = &schema.obj.all_of {
|
||||
for ao in all_of {
|
||||
props.extend(self.merged_properties(ao, visited));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(then_schema) = &schema.obj.then_ {
|
||||
props.extend(self.merged_properties(then_schema, visited));
|
||||
}
|
||||
|
||||
if let Some(else_schema) = &schema.obj.else_ {
|
||||
props.extend(self.merged_properties(else_schema, visited));
|
||||
}
|
||||
|
||||
if let Some(local_props) = &schema.obj.properties {
|
||||
for (k, v) in local_props {
|
||||
props.insert(k.clone(), v.clone());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(id) = &schema.obj.id {
|
||||
visited.remove(id);
|
||||
}
|
||||
|
||||
props
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user