merger now requires a schema id, queryer and merger now use pre-compiled edges for O(1) relations

This commit is contained in:
2026-03-21 20:33:28 -04:00
parent 9bdb767685
commit 882bdc6271
13 changed files with 1370 additions and 307 deletions

View File

@ -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
}
}