mirror of
				https://github.com/mealie-recipes/mealie.git
				synced 2025-10-30 17:53:31 -04:00 
			
		
		
		
	fix: CONTAINS ALL doesn't contain all (#5900)
This commit is contained in:
		| @@ -351,45 +351,46 @@ class QueryFilterBuilder: | ||||
|     ) -> sa.ColumnElement: | ||||
|         original_model_attr = model_attr | ||||
|         model_attr = cls._transform_model_attr(model_attr, model_attr_type) | ||||
|         value = component.validate(model_attr_type) | ||||
|  | ||||
|         # Keywords | ||||
|         if component.relationship is RelationalKeyword.IS: | ||||
|             element = model_attr.is_(component.validate(model_attr_type)) | ||||
|             element = model_attr.is_(value) | ||||
|         elif component.relationship is RelationalKeyword.IS_NOT: | ||||
|             element = model_attr.is_not(component.validate(model_attr_type)) | ||||
|             element = model_attr.is_not(value) | ||||
|         elif component.relationship is RelationalKeyword.IN: | ||||
|             element = model_attr.in_(component.validate(model_attr_type)) | ||||
|             element = model_attr.in_(value) | ||||
|         elif component.relationship is RelationalKeyword.NOT_IN: | ||||
|             vals = component.validate(model_attr_type) | ||||
|             if original_model_attr.parent.entity != model: | ||||
|                 subq = query.with_only_columns(model.id).where(model_attr.in_(vals)) | ||||
|                 subq = query.with_only_columns(model.id).where(model_attr.in_(value)) | ||||
|                 element = sa.not_(model.id.in_(subq)) | ||||
|             else: | ||||
|                 element = sa.not_(model_attr.in_(vals)) | ||||
|                 element = sa.not_(model_attr.in_(value)) | ||||
|  | ||||
|         elif component.relationship is RelationalKeyword.CONTAINS_ALL: | ||||
|             if len(value) == 1: | ||||
|                 element = model_attr.in_(value) | ||||
|             else: | ||||
|                 primary_model_attr: InstrumentedAttribute = getattr(model, component.attribute_name.split(".")[0]) | ||||
|             element = sa.and_() | ||||
|             for v in component.validate(model_attr_type): | ||||
|                 element = sa.and_(element, primary_model_attr.any(model_attr == v)) | ||||
|                 element = sa.and_(*(primary_model_attr.any(model_attr == v) for v in value)) | ||||
|         elif component.relationship is RelationalKeyword.LIKE: | ||||
|             element = model_attr.ilike(component.validate(model_attr_type)) | ||||
|             element = model_attr.ilike(value) | ||||
|         elif component.relationship is RelationalKeyword.NOT_LIKE: | ||||
|             element = model_attr.not_ilike(component.validate(model_attr_type)) | ||||
|             element = model_attr.not_ilike(value) | ||||
|  | ||||
|         # Operators | ||||
|         elif component.relationship is RelationalOperator.EQ: | ||||
|             element = model_attr == component.validate(model_attr_type) | ||||
|             element = model_attr == value | ||||
|         elif component.relationship is RelationalOperator.NOTEQ: | ||||
|             element = model_attr != component.validate(model_attr_type) | ||||
|             element = model_attr != value | ||||
|         elif component.relationship is RelationalOperator.GT: | ||||
|             element = model_attr > component.validate(model_attr_type) | ||||
|             element = model_attr > value | ||||
|         elif component.relationship is RelationalOperator.LT: | ||||
|             element = model_attr < component.validate(model_attr_type) | ||||
|             element = model_attr < value | ||||
|         elif component.relationship is RelationalOperator.GTE: | ||||
|             element = model_attr >= component.validate(model_attr_type) | ||||
|             element = model_attr >= value | ||||
|         elif component.relationship is RelationalOperator.LTE: | ||||
|             element = model_attr <= component.validate(model_attr_type) | ||||
|             element = model_attr <= value | ||||
|         else: | ||||
|             raise ValueError(f"invalid relationship {component.relationship}") | ||||
|  | ||||
|   | ||||
| @@ -488,6 +488,19 @@ def test_pagination_filter_in_advanced(unique_user: TestUser): | ||||
|     assert recipe_2.id not in recipe_ids | ||||
|     assert recipe_1_2.id in recipe_ids | ||||
|  | ||||
|     query = PaginationQuery( | ||||
|         page=1, | ||||
|         per_page=-1, | ||||
|         query_filter=f"tags.name CONTAINS ALL [{tag_1.name}]", | ||||
|     ) | ||||
|     recipe_results = database.recipes.page_all(query).items | ||||
|     assert len(recipe_results) == 2 | ||||
|     recipe_ids = {recipe.id for recipe in recipe_results} | ||||
|     assert recipe_0.id not in recipe_ids | ||||
|     assert recipe_1.id in recipe_ids | ||||
|     assert recipe_2.id not in recipe_ids | ||||
|     assert recipe_1_2.id in recipe_ids | ||||
|  | ||||
|  | ||||
| def test_pagination_filter_like(query_units: tuple[RepositoryUnit, IngredientUnit, IngredientUnit, IngredientUnit]): | ||||
|     units_repo, unit_1, unit_2, unit_3 = query_units | ||||
|   | ||||
		Reference in New Issue
	
	Block a user