diff --git a/src/queryer/compiler.rs b/src/queryer/compiler.rs index 1dc919e..642f5a6 100644 --- a/src/queryer/compiler.rs +++ b/src/queryer/compiler.rs @@ -496,6 +496,7 @@ impl<'a> Compiler<'a> { } self.compile_filter_conditions(r#type, type_aliases, &node, &base_alias, &mut where_clauses); + self.compile_polymorphic_bounds(r#type, type_aliases, &node, &mut where_clauses); self.compile_relation_conditions( r#type, type_aliases, @@ -507,6 +508,54 @@ impl<'a> Compiler<'a> { Ok(where_clauses) } + fn compile_polymorphic_bounds( + &self, + _type: &crate::database::r#type::Type, + type_aliases: &std::collections::HashMap, + node: &Node, + where_clauses: &mut Vec, + ) { + if let Some(edges) = node.schema.obj.compiled_edges.get() { + if let Some(props) = node.schema.obj.compiled_properties.get() { + for (prop_name, edge) in edges { + if let Some(prop_schema) = props.get(prop_name) { + // Determine if the property schema resolves to a physical Database Entity + let mut bound_type_name = None; + if let Some(family_target) = prop_schema.obj.family.as_ref() { + bound_type_name = Some(family_target.split('.').next_back().unwrap_or(family_target).to_string()); + } else if let Some(lookup_key) = prop_schema.obj.id.as_ref().or(prop_schema.obj.r#ref.as_ref()) { + bound_type_name = Some(lookup_key.split('.').next_back().unwrap_or(lookup_key).to_string()); + } + + if let Some(type_name) = bound_type_name { + // Ensure this type actually exists + if self.db.types.contains_key(&type_name) { + if let Some(relation) = self.db.relations.get(&edge.constraint) { + let mut poly_col = None; + let mut table_to_alias = ""; + + if edge.forward && relation.source_columns.len() > 1 { + poly_col = Some(&relation.source_columns[1]); // e.g., target_type + table_to_alias = &relation.source_type; // e.g., relationship + } else if !edge.forward && relation.destination_columns.len() > 1 { + poly_col = Some(&relation.destination_columns[1]); // e.g., source_type + table_to_alias = &relation.destination_type; // e.g., relationship + } + + if let Some(col) = poly_col { + if let Some(alias) = type_aliases.get(table_to_alias).or_else(|| type_aliases.get(&node.parent_alias)) { + where_clauses.push(format!("{}.{} = '{}'", alias, col, type_name)); + } + } + } + } + } + } + } + } + } + } + fn resolve_filter_alias( r#type: &crate::database::r#type::Type, type_aliases: &std::collections::HashMap,