diff --git a/fixtures/filter.json b/fixtures/filter.json index d15fd1a..c15a502 100644 --- a/fixtures/filter.json +++ b/fixtures/filter.json @@ -174,12 +174,48 @@ "person.filter": { "type": "filter", "compiledPropertyNames": [ + "$and", + "$or", "age", "billing_address", "birth_date", "first_name" ], "properties": { + "$and": { + "type": [ + "array", + "null" + ], + "items": { + "compiledPropertyNames": [ + "$and", + "$or", + "age", + "billing_address", + "birth_date", + "first_name" + ], + "type": "person.filter" + } + }, + "$or": { + "type": [ + "array", + "null" + ], + "items": { + "compiledPropertyNames": [ + "$and", + "$or", + "age", + "billing_address", + "birth_date", + "first_name" + ], + "type": "person.filter" + } + }, "first_name": { "type": [ "string.condition", @@ -210,9 +246,39 @@ "address.filter": { "type": "filter", "compiledPropertyNames": [ + "$and", + "$or", "city" ], "properties": { + "$and": { + "type": [ + "array", + "null" + ], + "items": { + "compiledPropertyNames": [ + "$and", + "$or", + "city" + ], + "type": "address.filter" + } + }, + "$or": { + "type": [ + "array", + "null" + ], + "items": { + "compiledPropertyNames": [ + "$and", + "$or", + "city" + ], + "type": "address.filter" + } + }, "city": { "type": [ "string.condition", @@ -230,10 +296,42 @@ "search.filter": { "type": "filter", "compiledPropertyNames": [ + "$and", + "$or", "filter", "name" ], "properties": { + "$and": { + "type": [ + "array", + "null" + ], + "items": { + "compiledPropertyNames": [ + "$and", + "$or", + "filter", + "name" + ], + "type": "search.filter" + } + }, + "$or": { + "type": [ + "array", + "null" + ], + "items": { + "compiledPropertyNames": [ + "$and", + "$or", + "filter", + "name" + ], + "type": "search.filter" + } + }, "filter": { "type": [ "filter.filter", diff --git a/src/database/compile/filter.rs b/src/database/compile/filter.rs index 7b3c8ff..67befaa 100644 --- a/src/database/compile/filter.rs +++ b/src/database/compile/filter.rs @@ -8,7 +8,7 @@ impl Schema { pub fn compile_filter( &self, _db: &Database, - _root_id: &str, + root_id: &str, _errors: &mut Vec, ) -> Option { if let Some(props) = self.obj.compiled_properties.get() { @@ -31,6 +31,48 @@ impl Schema { } if !filter_props.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, + 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, + always_fail: false, + }), + ); + let mut wrapper_obj = SchemaObject::default(); // Conceptually link this directly into the STI lineage of the base `filter` object wrapper_obj.type_ = Some(SchemaTypeOrArray::Single("filter".to_string())); diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 3c65476..6d85e4b 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -140,8 +140,22 @@ fn test_library_api() { "type": "object" }, "source_schema.filter": { - "compiledPropertyNames": ["name", "target", "type"], + "compiledPropertyNames": ["$and", "$or", "name", "target", "type"], "properties": { + "$and": { + "type": ["array", "null"], + "items": { + "compiledPropertyNames": ["$and", "$or", "name", "target", "type"], + "type": "source_schema.filter" + } + }, + "$or": { + "type": ["array", "null"], + "items": { + "compiledPropertyNames": ["$and", "$or", "name", "target", "type"], + "type": "source_schema.filter" + } + }, "name": { "type": ["string.condition", "null"] }, "target": { "type": ["target_schema.filter", "null"] }, "type": { "type": ["string.condition", "null"] } @@ -179,8 +193,22 @@ fn test_library_api() { "type": "object" }, "target_schema.filter": { - "compiledPropertyNames": ["value"], + "compiledPropertyNames": ["$and", "$or", "value"], "properties": { + "$and": { + "type": ["array", "null"], + "items": { + "compiledPropertyNames": ["$and", "$or", "value"], + "type": "target_schema.filter" + } + }, + "$or": { + "type": ["array", "null"], + "items": { + "compiledPropertyNames": ["$and", "$or", "value"], + "type": "target_schema.filter" + } + }, "value": { "type": ["number.condition", "null"] } }, "type": "filter"