stems removed from queryer
This commit is contained in:
@ -18,14 +18,11 @@ use executors::pgrx::SpiExecutor;
|
||||
#[cfg(test)]
|
||||
use executors::mock::MockExecutor;
|
||||
|
||||
pub mod stem;
|
||||
use punc::Punc;
|
||||
use relation::Relation;
|
||||
use schema::Schema;
|
||||
use serde_json::Value;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
use stem::Stem;
|
||||
use r#type::Type;
|
||||
|
||||
pub struct Database {
|
||||
@ -34,8 +31,6 @@ pub struct Database {
|
||||
pub puncs: HashMap<String, Punc>,
|
||||
pub relations: Vec<Relation>,
|
||||
pub schemas: HashMap<String, Schema>,
|
||||
// Map of Schema ID -> { Entity Type -> Target Subschema Arc }
|
||||
pub stems: HashMap<String, HashMap<String, Arc<Stem>>>,
|
||||
pub descendants: HashMap<String, Vec<String>>,
|
||||
pub depths: HashMap<String, usize>,
|
||||
pub executor: Box<dyn DatabaseExecutor + Send + Sync>,
|
||||
@ -49,7 +44,6 @@ impl Database {
|
||||
relations: Vec::new(),
|
||||
puncs: HashMap::new(),
|
||||
schemas: HashMap::new(),
|
||||
stems: HashMap::new(),
|
||||
descendants: HashMap::new(),
|
||||
depths: HashMap::new(),
|
||||
#[cfg(not(test))]
|
||||
@ -146,7 +140,6 @@ impl Database {
|
||||
self.collect_depths();
|
||||
self.collect_descendants();
|
||||
self.compile_schemas();
|
||||
self.collect_stems()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -325,236 +318,4 @@ impl Database {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_stems(&mut self) -> Result<(), crate::drop::Drop> {
|
||||
let mut db_stems: HashMap<String, HashMap<String, Arc<Stem>>> = HashMap::new();
|
||||
let mut errors: Vec<crate::drop::Error> = Vec::new();
|
||||
|
||||
let schema_ids: Vec<String> = self.schemas.keys().cloned().collect();
|
||||
for schema_id in schema_ids {
|
||||
if let Some(schema) = self.schemas.get(&schema_id) {
|
||||
let mut inner_map = HashMap::new();
|
||||
Self::discover_stems(
|
||||
self,
|
||||
&schema_id,
|
||||
schema,
|
||||
String::from(""),
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
&mut inner_map,
|
||||
Vec::new(),
|
||||
&mut errors,
|
||||
);
|
||||
if !inner_map.is_empty() {
|
||||
db_stems.insert(schema_id, inner_map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.stems = db_stems;
|
||||
|
||||
if !errors.is_empty() {
|
||||
return Err(crate::drop::Drop::with_errors(errors));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn discover_stems(
|
||||
db: &Database,
|
||||
root_schema_id: &str,
|
||||
schema: &Schema,
|
||||
current_path: String,
|
||||
parent_type: Option<String>,
|
||||
property_name: Option<String>,
|
||||
is_polymorphic: bool,
|
||||
inner_map: &mut HashMap<String, Arc<Stem>>,
|
||||
seen_entities: Vec<String>,
|
||||
errors: &mut Vec<crate::drop::Error>,
|
||||
) {
|
||||
let mut is_entity = false;
|
||||
let mut entity_type = String::new();
|
||||
|
||||
// First check if the Schema's $id is a native Database Type
|
||||
if let Some(ref id) = schema.obj.id {
|
||||
let parts: Vec<&str> = id.split('.').collect();
|
||||
if let Some(last_seg) = parts.last() {
|
||||
if db.types.contains_key(*last_seg) {
|
||||
is_entity = true;
|
||||
entity_type = last_seg.to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If not found via $id, check the $ref pointer
|
||||
// This allows ad-hoc schemas (like `save_person.response`) to successfully adopt the Type of what they $ref
|
||||
if !is_entity {
|
||||
if let Some(ref r) = schema.obj.r#ref {
|
||||
let parts: Vec<&str> = r.split('.').collect();
|
||||
if let Some(last_seg) = parts.last() {
|
||||
if db.types.contains_key(*last_seg) {
|
||||
is_entity = true;
|
||||
entity_type = last_seg.to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if is_entity {
|
||||
if seen_entities.contains(&entity_type) {
|
||||
return; // Break cyclical schemas!
|
||||
}
|
||||
}
|
||||
|
||||
let mut relation_col = None;
|
||||
if is_entity {
|
||||
if let (Some(pt), Some(prop)) = (&parent_type, &property_name) {
|
||||
let expected_col = format!("{}_id", prop);
|
||||
let mut found = false;
|
||||
|
||||
if let Some((rel, _)) = db.get_relation(pt, &entity_type, prop, None) {
|
||||
if rel.source_columns.contains(&expected_col) {
|
||||
relation_col = Some(expected_col.clone());
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
relation_col = Some(expected_col);
|
||||
}
|
||||
}
|
||||
|
||||
let mut final_path = current_path.clone();
|
||||
if is_polymorphic && !final_path.is_empty() && !final_path.ends_with(&entity_type) {
|
||||
if final_path.ends_with(".#") {
|
||||
final_path = format!("{}(type==\"{}\")", final_path, entity_type);
|
||||
} else {
|
||||
final_path = format!("{}#(type==\"{}\")", final_path, entity_type);
|
||||
}
|
||||
}
|
||||
|
||||
let stem = Stem {
|
||||
r#type: entity_type.clone(),
|
||||
relation: relation_col,
|
||||
schema: Arc::new(schema.clone()),
|
||||
};
|
||||
inner_map.insert(final_path, Arc::new(stem));
|
||||
}
|
||||
|
||||
let next_parent = if is_entity {
|
||||
Some(entity_type.clone())
|
||||
} else {
|
||||
parent_type.clone()
|
||||
};
|
||||
|
||||
let pass_seen = if is_entity {
|
||||
let mut ns = seen_entities.clone();
|
||||
ns.push(entity_type.clone());
|
||||
ns
|
||||
} else {
|
||||
seen_entities.clone()
|
||||
};
|
||||
|
||||
// Properties branch
|
||||
if let Some(props) = &schema.obj.properties {
|
||||
for (k, v) in props {
|
||||
// Standard Property Pathing
|
||||
let next_path = if current_path.is_empty() {
|
||||
k.clone()
|
||||
} else {
|
||||
format!("{}.{}", current_path, k)
|
||||
};
|
||||
|
||||
Self::discover_stems(
|
||||
db,
|
||||
root_schema_id,
|
||||
v,
|
||||
next_path,
|
||||
next_parent.clone(),
|
||||
Some(k.clone()),
|
||||
false,
|
||||
inner_map,
|
||||
pass_seen.clone(),
|
||||
errors,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Array Item branch
|
||||
if let Some(items) = &schema.obj.items {
|
||||
let next_path = if current_path.is_empty() {
|
||||
String::from("#")
|
||||
} else {
|
||||
format!("{}.#", current_path)
|
||||
};
|
||||
|
||||
Self::discover_stems(
|
||||
db,
|
||||
root_schema_id,
|
||||
items,
|
||||
next_path,
|
||||
next_parent.clone(),
|
||||
property_name.clone(),
|
||||
false,
|
||||
inner_map,
|
||||
pass_seen.clone(),
|
||||
errors,
|
||||
);
|
||||
}
|
||||
|
||||
// Follow external reference if we didn't just crawl local properties
|
||||
if schema.obj.properties.is_none() && schema.obj.items.is_none() && schema.obj.one_of.is_none()
|
||||
{
|
||||
if let Some(ref r) = schema.obj.r#ref {
|
||||
if let Some(target_schema) = db.schemas.get(r) {
|
||||
Self::discover_stems(
|
||||
db,
|
||||
root_schema_id,
|
||||
target_schema,
|
||||
current_path.clone(),
|
||||
next_parent.clone(),
|
||||
property_name.clone(),
|
||||
is_polymorphic,
|
||||
inner_map,
|
||||
seen_entities.clone(),
|
||||
errors,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Polymorphism branch
|
||||
if let Some(arr) = &schema.obj.one_of {
|
||||
for v in arr {
|
||||
Self::discover_stems(
|
||||
db,
|
||||
root_schema_id,
|
||||
v.as_ref(),
|
||||
current_path.clone(),
|
||||
next_parent.clone(),
|
||||
property_name.clone(),
|
||||
true,
|
||||
inner_map,
|
||||
pass_seen.clone(),
|
||||
errors,
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(arr) = &schema.obj.all_of {
|
||||
for v in arr {
|
||||
Self::discover_stems(
|
||||
db,
|
||||
root_schema_id,
|
||||
v.as_ref(),
|
||||
current_path.clone(),
|
||||
next_parent.clone(),
|
||||
property_name.clone(),
|
||||
is_polymorphic,
|
||||
inner_map,
|
||||
pass_seen.clone(),
|
||||
errors,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
use crate::database::schema::Schema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Stem {
|
||||
pub r#type: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub relation: Option<String>,
|
||||
|
||||
pub schema: Arc<Schema>,
|
||||
}
|
||||
Reference in New Issue
Block a user