checkpoint
This commit is contained in:
@ -1,5 +1,4 @@
|
||||
use crate::database::Database;
|
||||
use std::sync::Arc;
|
||||
pub struct Compiler<'a> {
|
||||
pub db: &'a Database,
|
||||
pub filter_keys: &'a [String],
|
||||
@ -124,35 +123,19 @@ impl<'a> Compiler<'a> {
|
||||
return Err(format!("Unresolved schema type pointer: {}", t));
|
||||
}
|
||||
}
|
||||
// Handle $family Polymorphism fallbacks for relations
|
||||
if let Some(family_target) = &node.schema.obj.family {
|
||||
let mut all_targets = vec![family_target.clone()];
|
||||
if let Some(descendants) = self.db.descendants.get(family_target) {
|
||||
all_targets.extend(descendants.clone());
|
||||
}
|
||||
|
||||
if all_targets.len() == 1 {
|
||||
let mut bypass_schema = crate::database::schema::Schema::default();
|
||||
bypass_schema.obj.type_ = Some(crate::database::schema::SchemaTypeOrArray::Single(all_targets[0].clone()));
|
||||
let mut bypass_node = node.clone();
|
||||
bypass_node.schema = std::sync::Arc::new(bypass_schema);
|
||||
return self.compile_node(bypass_node);
|
||||
}
|
||||
|
||||
all_targets.sort();
|
||||
let mut family_schemas = Vec::new();
|
||||
for variation in &all_targets {
|
||||
let mut ref_schema = crate::database::schema::Schema::default();
|
||||
ref_schema.obj.type_ = Some(crate::database::schema::SchemaTypeOrArray::Single(variation.clone()));
|
||||
family_schemas.push(std::sync::Arc::new(ref_schema));
|
||||
}
|
||||
|
||||
return self.compile_one_of(&family_schemas, node);
|
||||
}
|
||||
|
||||
// Handle oneOf Polymorphism fallbacks for relations
|
||||
if let Some(one_of) = &node.schema.obj.one_of {
|
||||
return self.compile_one_of(one_of, node.clone());
|
||||
// Handle Polymorphism fallbacks for relations
|
||||
if node.schema.obj.family.is_some() || node.schema.obj.one_of.is_some() {
|
||||
if let Some(options) = node.schema.obj.compiled_options.get() {
|
||||
if options.len() == 1 {
|
||||
let target_id = options.values().next().unwrap();
|
||||
let mut bypass_schema = crate::database::schema::Schema::default();
|
||||
bypass_schema.obj.type_ = Some(crate::database::schema::SchemaTypeOrArray::Single(target_id.clone()));
|
||||
let mut bypass_node = node.clone();
|
||||
bypass_node.schema = std::sync::Arc::new(bypass_schema);
|
||||
return self.compile_node(bypass_node);
|
||||
}
|
||||
}
|
||||
return self.compile_one_of(node);
|
||||
}
|
||||
|
||||
// Just an inline object definition?
|
||||
@ -226,77 +209,43 @@ impl<'a> Compiler<'a> {
|
||||
) -> Result<Vec<String>, String> {
|
||||
let mut select_args = Vec::new();
|
||||
|
||||
if let Some(family_target) = node.schema.obj.family.as_ref() {
|
||||
let family_prefix = family_target.rfind('.').map(|idx| &family_target[..idx]);
|
||||
|
||||
let mut all_targets = vec![family_target.clone()];
|
||||
if let Some(descendants) = self.db.descendants.get(family_target) {
|
||||
all_targets.extend(descendants.clone());
|
||||
}
|
||||
|
||||
// Filter targets to EXACTLY match the family_target prefix
|
||||
let mut final_targets = Vec::new();
|
||||
for target in all_targets {
|
||||
let target_prefix = target.rfind('.').map(|idx| &target[..idx]);
|
||||
if target_prefix == family_prefix {
|
||||
final_targets.push(target);
|
||||
}
|
||||
}
|
||||
|
||||
final_targets.sort();
|
||||
final_targets.dedup();
|
||||
|
||||
if final_targets.len() == 1 {
|
||||
let variation = &final_targets[0];
|
||||
if let Some(target_schema) = self.db.schemas.get(variation) {
|
||||
let mut bypass_node = node.clone();
|
||||
bypass_node.schema = std::sync::Arc::new(target_schema.clone());
|
||||
|
||||
let mut bypassed_args = self.compile_select_clause(r#type, table_aliases, bypass_node)?;
|
||||
select_args.append(&mut bypassed_args);
|
||||
} else {
|
||||
return Err(format!("Could not find schema for variation {}", variation));
|
||||
}
|
||||
} else {
|
||||
let mut family_schemas = Vec::new();
|
||||
|
||||
for variation in &final_targets {
|
||||
if let Some(target_schema) = self.db.schemas.get(variation) {
|
||||
family_schemas.push(std::sync::Arc::new(target_schema.clone()));
|
||||
} else {
|
||||
return Err(format!(
|
||||
"Could not find schema metadata for variation {}",
|
||||
variation
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if node.schema.obj.family.is_some() || node.schema.obj.one_of.is_some() {
|
||||
let base_alias = table_aliases
|
||||
.get(&r#type.name)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| node.parent_alias.to_string());
|
||||
|
||||
let disc = node.schema.obj.compiled_discriminator.get();
|
||||
if disc.is_none() {
|
||||
return Ok(select_args);
|
||||
}
|
||||
|
||||
let options = node.schema.obj.compiled_options.get();
|
||||
println!("[DEBUG QUERYER] Evaluating node. Target family: {:?}, disc: {:?}, options: {:?}", node.schema.obj.family, disc, options);
|
||||
if options.is_none() {
|
||||
return Ok(select_args);
|
||||
}
|
||||
let options = options.unwrap();
|
||||
|
||||
if options.len() == 1 {
|
||||
let target_id = options.values().next().unwrap();
|
||||
if let Some(target_schema) = self.db.schemas.get(target_id) {
|
||||
let mut bypass_node = node.clone();
|
||||
bypass_node.schema = std::sync::Arc::new(target_schema.clone());
|
||||
let mut bypassed_args = self.compile_select_clause(r#type, table_aliases, bypass_node)?;
|
||||
select_args.append(&mut bypassed_args);
|
||||
return Ok(select_args);
|
||||
}
|
||||
}
|
||||
|
||||
select_args.push(format!("'id', {}.id", base_alias));
|
||||
let mut case_node = node.clone();
|
||||
case_node.parent_alias = base_alias.clone();
|
||||
let arc_aliases = std::sync::Arc::new(table_aliases.clone());
|
||||
case_node.parent_type_aliases = Some(arc_aliases);
|
||||
|
||||
let (case_sql, _) = self.compile_one_of(&family_schemas, case_node)?;
|
||||
select_args.push(format!("'type', {}", case_sql));
|
||||
}
|
||||
} else if let Some(one_of) = &node.schema.obj.one_of {
|
||||
let base_alias = table_aliases
|
||||
.get(&r#type.name)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| node.parent_alias.to_string());
|
||||
select_args.push(format!("'id', {}.id", base_alias));
|
||||
let mut case_node = node.clone();
|
||||
case_node.parent_alias = base_alias.clone();
|
||||
let arc_aliases = std::sync::Arc::new(table_aliases.clone());
|
||||
case_node.parent_type_aliases = Some(arc_aliases);
|
||||
|
||||
let (case_sql, _) = self.compile_one_of(one_of, case_node)?;
|
||||
select_args.push(format!("'type', {}", case_sql));
|
||||
let (case_sql, _) = self.compile_one_of(case_node)?;
|
||||
select_args.push(format!("'{}', {}", disc.unwrap(), case_sql));
|
||||
}
|
||||
|
||||
Ok(select_args)
|
||||
@ -333,26 +282,28 @@ impl<'a> Compiler<'a> {
|
||||
|
||||
fn compile_one_of(
|
||||
&mut self,
|
||||
schemas: &[Arc<crate::database::schema::Schema>],
|
||||
node: Node<'a>,
|
||||
) -> Result<(String, String), String> {
|
||||
let mut case_statements = Vec::new();
|
||||
|
||||
let options = node.schema.obj.compiled_options.get().ok_or("Missing compiled options for polymorphism")?;
|
||||
let disc = node.schema.obj.compiled_discriminator.get().ok_or("Missing compiled discriminator for polymorphism")?;
|
||||
|
||||
let type_col = if let Some(prop) = &node.property_name {
|
||||
format!("{}_type", prop)
|
||||
format!("{}_{}", prop, disc)
|
||||
} else {
|
||||
"type".to_string()
|
||||
disc.to_string()
|
||||
};
|
||||
|
||||
for option_schema in schemas {
|
||||
if let Some(base_type_name) = option_schema.obj.identifier() {
|
||||
// Generate the nested SQL for this specific target type
|
||||
for (disc_val, target_id) in options {
|
||||
if let Some(target_schema) = self.db.schemas.get(target_id) {
|
||||
let mut child_node = node.clone();
|
||||
child_node.schema = std::sync::Arc::clone(option_schema);
|
||||
child_node.schema = std::sync::Arc::new(target_schema.clone());
|
||||
let (val_sql, _) = self.compile_node(child_node)?;
|
||||
|
||||
case_statements.push(format!(
|
||||
"WHEN {}.{} = '{}' THEN ({})",
|
||||
node.parent_alias, type_col, base_type_name, val_sql
|
||||
node.parent_alias, type_col, disc_val, val_sql
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user