fixed nested filters

This commit is contained in:
2026-04-24 10:48:38 -04:00
parent 45ebc57e0c
commit 0093aea790
2 changed files with 121 additions and 57 deletions

View File

@ -14,7 +14,35 @@ impl Schema {
if let Some(props) = self.obj.compiled_properties.get() {
let mut filter_props = BTreeMap::new();
for (key, child) in props {
if let Some(mut filter_type) = Self::resolve_filter_type(child) {
let mut structural_filter = None;
let is_array = match &child.obj.type_ {
Some(SchemaTypeOrArray::Single(t)) => t == "array",
Some(SchemaTypeOrArray::Multiple(types)) => types.contains(&"array".to_string()),
None => false,
};
if is_array {
if let Some(items) = &child.obj.items {
if !items.is_proxy() {
structural_filter = items.compile_filter(_db, "", _errors);
}
}
} else if !child.is_proxy() {
structural_filter = child.compile_filter(_db, "", _errors);
}
if let Some(mut inline_schema) = structural_filter {
inline_schema.obj.type_ = Some(SchemaTypeOrArray::Multiple(vec![
"object".to_string(),
"null".to_string(),
]));
filter_props.insert(
key.clone(),
Arc::new(inline_schema),
);
} else if let Some(mut filter_type) = Self::resolve_filter_type(child) {
filter_type.push("null".to_string());
let mut child_obj = SchemaObject::default();
@ -31,47 +59,49 @@ impl Schema {
}
if !filter_props.is_empty() {
let root_filter_type = format!("{}.filter", root_id);
if !root_id.is_empty() {
let root_filter_type = format!("{}.filter", root_id);
let mut and_obj = SchemaObject::default();
and_obj.type_ = Some(SchemaTypeOrArray::Multiple(vec![
"array".to_string(),
"null".to_string(),
]));
and_obj.items = Some(Arc::new(Schema {
obj: SchemaObject {
type_: Some(SchemaTypeOrArray::Single(root_filter_type.clone())),
..Default::default()
},
always_fail: false,
}));
filter_props.insert(
"$and".to_string(),
Arc::new(Schema {
obj: and_obj,
let mut and_obj = SchemaObject::default();
and_obj.type_ = Some(SchemaTypeOrArray::Multiple(vec![
"array".to_string(),
"null".to_string(),
]));
and_obj.items = Some(Arc::new(Schema {
obj: SchemaObject {
type_: Some(SchemaTypeOrArray::Single(root_filter_type.clone())),
..Default::default()
},
always_fail: false,
}),
);
}));
filter_props.insert(
"$and".to_string(),
Arc::new(Schema {
obj: and_obj,
always_fail: false,
}),
);
let mut or_obj = SchemaObject::default();
or_obj.type_ = Some(SchemaTypeOrArray::Multiple(vec![
"array".to_string(),
"null".to_string(),
]));
or_obj.items = Some(Arc::new(Schema {
obj: SchemaObject {
type_: Some(SchemaTypeOrArray::Single(root_filter_type.clone())),
..Default::default()
},
always_fail: false,
}));
filter_props.insert(
"$or".to_string(),
Arc::new(Schema {
obj: or_obj,
let mut or_obj = SchemaObject::default();
or_obj.type_ = Some(SchemaTypeOrArray::Multiple(vec![
"array".to_string(),
"null".to_string(),
]));
or_obj.items = Some(Arc::new(Schema {
obj: SchemaObject {
type_: Some(SchemaTypeOrArray::Single(root_filter_type.clone())),
..Default::default()
},
always_fail: false,
}),
);
}));
filter_props.insert(
"$or".to_string(),
Arc::new(Schema {
obj: or_obj,
always_fail: false,
}),
);
}
let mut wrapper_obj = SchemaObject::default();
// Filters are just plain objects containing conditions, no inheritance required
@ -119,7 +149,12 @@ impl Schema {
"number" => Some(vec!["number.condition".to_string()]),
"boolean" => Some(vec!["boolean.condition".to_string()]),
"object" => None, // Inline structures are ignored in Composed References
"array" => None, // We don't filter primitive arrays or map complex arrays yet
"array" => {
if let Some(items) = &schema.obj.items {
return Self::resolve_filter_type(items);
}
None
},
"null" => None,
custom => {
// Assume anything else is a Relational cross-boundary that already has its own .filter dynamically built