-
Notifications
You must be signed in to change notification settings - Fork 822
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FIX: DRAFT ! equate empty string to null for more intuitive results #11363
base: 5
Are you sure you want to change the base?
Conversation
Is the "DRAFT" in the pr title part of the context, or do you mean the pr is a draft and shouldn't be reviewed yet? |
DRAFT as in: I would like for someone to have a look at it for some feedback. I know it can not be merged like this, but I can't progress, because I need it to be reviewed. |
That seems like an outright bug. What's actually stored in the database? Is it set to |
It is stored as a NULL value. I will run it again on a different project, just to be sure it is correct. |
My general feeling on this is that is dangerous to assume your opening statement:
While I appreciate that you are trying to make things more "intuitive", there's a balance to be had here between things that feel right, and things that are objectively correct. I think an approach to take would be to be able to pass a specific token into the filter that means "empty" - to your specific example, something like: foreach(MyDataObject::get() as $myObject) {
$myObject->MyField = '';
$myObject->write();
}
echo
MyDataObject::get()->count() .
'=' .
MyDataObject::get()->filter(['MyField' => DB::EMPTY_TOKEN])->count()
; where |
Ahh okay that makes sense then. So yeah filtering by empty string and treating it as I think at best this would have to be configurable. |
No, that is not dangerous, that is a fact. Just ask 100 content editors - do you care about the difference between null and an empty string. In real life, they are usually the same thing. I appreciate that NULL basically means: "no set" and an empty string a particular value that is set. That is not lost on me, but Silverstripe is for the real world. |
The problem with this is that we do not always control what we filter for, if you filter for a variable (e.g. from a form input), then you need to consider this every time. I guess what I am saying is that the NULL vs EMPTY STRING is an edge case, not the other way around. |
I like @andrewandante's suggestion of having a const that people can use - that helps to remove the ambiguity. Though it does depend on developers knowing that's there to use which I think will be the hard part. |
Content editors aren't the ones setting up the data model and using the ORM :p There are times where programatically the value difference is important. |
I think it should be the other way around. If you filter for NULL or EMPTY STRING it should yield the same result, unless you set some "strict" setting, in which case it would go for NULL or EMPTY STRING only. |
To sum up what's being discussed in the Silverstripe User's Slack at the moment:
For more of my own opinions 😅
^ I agree with this sentiment entirely. Yes, content authors aren't expect to know the difference between
I think the preference here comes down to which way we lean. If we go for the magic route, we want to lean towards a loose match, with |
Description
In the real world, there is often little difference between null and an empty string (''). For a developer it is not easy to know if a field is saved as an empty string or null or how that works, especially if you are new to Silverstripe (or if you are focussing on the actual problem and do not really care about these sort of details).
In my case, I wrote:
In my simple thinking, I was like, anything with a real entry (i.e. not NULL, EMPTY STRING, or ZERO). What I noticed though is that LESS rows were included than expected.
Now, also consider this: For example, if you write:
You will see that the answer is
foo=0
, wherefoo
is obviously the number of records. That is not intuitive.I have investigated this a little and by taking two random DataObjects with a Varchar field and filtering for "falsy" vs non-falsy. With interesting results. I will list the results below.
I tried to fix this by just poking around and what I got up to so far is a the attached pull requests. This is just a trial pull request to see if it works! Obviously this is a super risky "breaking" change so improvements are:
An alternative would be too simply throw an error for any query where the value is an empty string to warn developers that the results may not be as expected.
Another alternative would be to keep the code as-is, but to make the NULL filter requirement a lot more obvious in the documentation.
Of course, one of the more "hidden" scenarios is, for example, when filtering using a variable that can be any string (including an empty one). In this scenario, as developer, you would simply forget to turn an empty string (one of many strings) into a NULL value.
Issues
These may be related:
#10930
#8135
From Nightjarnz:
https://github.com/silverstripe/silverstripe-framework/blob/5/src/ORM/Filters/ExactMatchFilter.php#L118
https://github.com/silverstripe/silverstripe-framework/blob/5/src/ORM/Filters/ExactMatchFilter.php#L221-L223
Pull request checklist
Manual testing steps
Click to see the very long details
results from test before changing code (search for WRONG to see 18 unexpected results):
results from test after changing code (note only two, "expected" errors):