The content module as currently configured will not store a NULL value. The content_field() function doesn't check if NULL values are allowed or handle them differently, it just converts values based on the field type (varchar or int), which then turns a blank varchar value into '' and a blank int value into 0 and stores that value in the database. As it stands, there is no way to get content_field() to store a NULL value even in a field that has been defined to allow NULL values.
A related problem is that there is no way to differentiate between a blank value and a NULL value in the $node array. If you save a value in the array as NULL, it looks the same as a blank (''), and not all blanks should be stored as NULLs.
I have been trying to allow for non-required fields in the date module (http://drupal.org/node/72085) by re-structuring the database to allow for NULL values, then altering the module code to store a NULL value for empty fields. A NULL value is needed for empty date fields because 0 is a valid value for a timestamp field that should not be used to represent an empty value. Other field modules may need to differentiate between NULL and zero or blank values for empty, non-required fields, like the number and optionwidgets modules.
Attached is a patch against the 4.7 version of the module to try to address this problem. Before storing the value I add a check for whether the value is empty and the field is configured to accept NULL values and the field is not required. If it passes all those tests, the query is altered to save the value as NULL, otherwise the query is saves the value as it always has. I'm not sure that test correctly catches all possibilities, but it seems like a good start. The same change would be needed for the cvs version, but that version is kind of in limbo now as it gets caught up to HEAD, so I didn't try to make a patch for it.
| Comment | File | Size | Author |
|---|---|---|---|
| #7 | content.module_11.patch | 2.05 KB | karens |
| #6 | content.module_10.patch | 2.05 KB | karens |
| content.module_9.patch | 4.66 KB | karens |
Comments
Comment #1
karens commentedMarking this as a patch.
Comment #2
yched commentedI've simply been looking at the code for now.
One question : where does the value of
$attributes['not null']come from ?is it already there in content.module, or is this an additional checkbox on the field settings page ?
Comment #3
karens commentedIt's established in the install file and in the 'columns' attributes for the field. There is no checkbox setting, this is hardcoded into the module.
What has happened is that all the cck fields were originally set up to be not null (which is why we're having problems with empty values defaulting to zero). The install and columns code has options for this, so it's obviously intended to allow null values. I think it's just that since they aren't being used anywhere no one ever noticed that you can't actually save null values to the database. So as it stands, you can create fields that will accept null values, but you can't save a null value to the field.
Comment #4
yched commentedI'm trying to review this. but I'm not sure what exactly I'm supposed to observe.
I applied the patch
I changed "not null" => TRUE to "not null" => FALSE in number.module,
deleted the cck cache entry, and created a new content type, with an integer field
Here's what I see
when I enter 2, 2 is stored : OK
when I enter nothing, NULL is stored : OK (I guess before the patch it would have been 0)
when I enter 0, NULL is stored : not OK
if the field is multiple
when I enter 2 (empty) 2, 2 NULL 2 is stored : OK, but on node display and on next edit it's just as if I had entered 2 2 - is that OK ?
when I enter 2 0 2, 2 NULL 2 is stored : not OK
I'm not sure if the not OK's denote a hole in your patch or just adjustments that would be necessary in, for instance, number.module ?
Comment #5
karens commentedcorrect, that was the problem
see below
I haven't made any attempt to figure out what changes are needed to display the null value correctly, that probably needs to be done module by module. I'm just trying to find a way to save it.
As I noted in the original patch:
That's why 0s are getting saved as nulls. So we need a way to differentiate empty and null values in the $node array, which will also involve changes in the individual field modules. For instance we could alter the form processing code to put 'NULL' into the node array to make it clear where NULL should be used instead of 0 or '', then change the patch a bit to test for 'NULL' instead of testing for empty.
Comment #6
karens commentedOK, here's a slightly different approach. It stores the null value only if 'NULL' (a string not a real NULL) is saved to the node array. That way nothing happens unless the module specifically sets up a node array to be saved with null values. This will break no existing behavior, just make it possible for field modules to store null values.
Then the field modules would need to:
1) alter the install file and columns array to create a field that can contain null values (may require a database update)
2) alter the form processing code to identify when a null value should be saved and save 'NULL' to the node field array in that case
3) alter the form display to do whatever should happen if the field value is null.
Comment #7
karens commentedI now have the cvs version of the date field ready to use this so it can be tested and I think it works most naturally by testing if the value is blank (not empty) and the field is not required and the field can store null values, so here is (yet another) patch. You can then use this patch and the cvs version of the date module to store empty date field values as nulls.
Comment #8
karens commentedI went ahead and committed this patch. It was working for me and I haven't gotten any other feedback, but it's a necessary first step to getting the number and date modules to properly handle empty non-required fields without storing the empty value as a zero.
Comment #9
(not verified) commented