InvalidArgumentException: Cannot filter "ClassName"."FieldName" against an empty set

Silverstripe Version: 4.2.1

Question:

Hi,

I’m using DataList’s filterAny() method to produce an SQL query like “MyField IN (possible values here)”. Sometimes the possible values are an empty array, in which case the result should actually be an empty DataList. This is how it worked in the latest versions of SS3, but in SS4 it has been changed. Now it throws an InvalidArgumentException if the array is empty.

I understand that an empty array should not produce a query like “MyField IN ()” because that would be incorrect syntax. But it could just prevent making a query and return an empty DataList. Now I have to do some cumbersome checking if the array is empty before calling filterAny().

An example how to reproduce this problem:

$possible_values = some_function(); //Returns an array, which can sometimes be empty
$objects = new DataList('MyModel')->filterAny('MyField', $possible_values);

If the array is empty, an InvalidArgumentException is thrown. Here is part of the code that throws that Exception:

vendor/silverstripe/framework/src/ORM/Filters/ExactMatchFilter.php:

protected function manyFilter(DataQuery $query, $inclusive)
    {
        $this->model = $query->applyRelation($this->relation);
        $caseSensitive = $this->getCaseSensitive();
        // Check values for null
        $field = $this->getDbName();
        $values = $this->getValue();
        if (empty($values)) {
            throw new \InvalidArgumentException("Cannot filter {$field} against an empty set");
        }
        $hasNull = in_array(null, $values, true);
        if ($hasNull) {
            $values = array_filter($values, function ($value) {
                return $value !== null;
            });
        }
       // ...
}

So I’m asking if the Exception is reasonable? Or is there another search filter modifier which I could use instead of ExactMatch?

Thank you for your support! :slight_smile:

If the array is empty, and you expect that to return an empty DataList, why bother even running the query? The exception is there to say that it can’t run a query with the input provided, not to make a choice about what it should return in that case - The logic for that should be in your code. It’s no more cumbersome for you to wrap your code in if (!empty($possible_values)) than it would be anywhere else.

Seems to me that you can just check the the array, and if it’s empty, return null - that way you’re also saving yourself a database query / function call which will save you some time.

The problem with the manyFilter() returning a result for an invalid input is that it would make no distinction between a valid search which returns no results, and an invalid search - and that might be important.