Fixed filter logic for exclusion of entities. Before parts with null values as property value were wrongly not shown

This fixes  issue #658
This commit is contained in:
Jan Böhmer 2024-08-23 22:58:04 +02:00
parent 5231dbd6e7
commit 7fc3153dde
2 changed files with 17 additions and 5 deletions

View file

@ -137,7 +137,7 @@ class EntityConstraint extends AbstractConstraint
}
//We need to handle null values differently, as they can not be compared with == or !=
if (!$this->value instanceof AbstractDBElement) {
if ($this->value === null) {
if($this->operator === '=' || $this->operator === 'INCLUDING_CHILDREN') {
$queryBuilder->andWhere(sprintf("%s IS NULL", $this->property));
return;
@ -152,8 +152,9 @@ class EntityConstraint extends AbstractConstraint
}
if($this->operator === '=' || $this->operator === '!=') {
$this->addSimpleAndConstraint($queryBuilder, $this->property, $this->identifier, $this->operator, $this->value);
return;
//Include null values on != operator, so that really all values are returned that are not equal to the given value
$this->addSimpleAndConstraint($queryBuilder, $this->property, $this->identifier, $this->operator, $this->value, $this->operator === '!=');
return;
}
//Otherwise retrieve the children list and apply the operator to it
@ -168,7 +169,8 @@ class EntityConstraint extends AbstractConstraint
}
if ($this->operator === 'EXCLUDING_CHILDREN') {
$this->addSimpleAndConstraint($queryBuilder, $this->property, $this->identifier, 'NOT IN', $list);
//Include null values in the result, so that all elements that are not in the list are returned
$this->addSimpleAndConstraint($queryBuilder, $this->property, $this->identifier, 'NOT IN', $list, true);
return;
}
} else {

View file

@ -56,8 +56,14 @@ trait FilterTrait
/**
* Adds a simple constraint in the form of (property OPERATOR value) (e.g. "part.name = :name") to the given query builder.
* @param QueryBuilder $queryBuilder The query builder to add the constraint to
* @param string $property The property to compare
* @param string $parameterIdentifier The identifier for the parameter
* @param string $comparison_operator The comparison operator to use
* @param mixed $value The value to compare to
* @param bool $include_null If true, the result of this constraint will also include null values of this property (useful for exclusion filters)
*/
protected function addSimpleAndConstraint(QueryBuilder $queryBuilder, string $property, string $parameterIdentifier, string $comparison_operator, mixed $value): void
protected function addSimpleAndConstraint(QueryBuilder $queryBuilder, string $property, string $parameterIdentifier, string $comparison_operator, mixed $value, bool $include_null = false): void
{
if ($comparison_operator === 'IN' || $comparison_operator === 'NOT IN') {
$expression = sprintf("%s %s (:%s)", $property, $comparison_operator, $parameterIdentifier);
@ -65,6 +71,10 @@ trait FilterTrait
$expression = sprintf("%s %s :%s", $property, $comparison_operator, $parameterIdentifier);
}
if ($include_null) {
$expression = sprintf("(%s OR %s IS NULL)", $expression, $property);
}
if($this->useHaving || $this->isAggregateFunctionString($property)) { //If the property is an aggregate function, we have to use the "having" instead of the "where"
$queryBuilder->andHaving($expression);
} else {