If db_write_record() is passed an array and the insertion fails for any reason, it throws an exception. However, it does not handle the exception and turn the passed-in object back to an array.
To reproduce the bug, I have attached a simple demo module. Essentially, any kind of insert which will throw will do the job. Use something like this:
$entry = array(.... whatever);
try {
$result = drupal_write_record('db_write_record_bug', $entry);
}
catch (Exception $e) {
drupal_set_message(t('Insertion: drupal_write_record failed. typeof($entry)=@type, Message = %message, query= %query',
array('@type' => gettype($entry), '%message' => $e->getMessage(), '%query' => $e->query_string)), 'error');
}
What I expect to happen: An exception is thrown and $object (which is an array in this case) is unchanged... or at least it's still an array.
What happens: $entry is converted silently to an object, meaning that the caller will likely get fatal errors trying to deal with the error.
The attached patch is a way to handle this without interface changes. I think it might be better not to pass $object by reference - that way arrays would be unaffected by this function.
The patch is tiny (just a try/catch). It shows up as a few lines because of the indentation of the affected block.
Comment | File | Size | Author |
---|---|---|---|
#2 | db_write_record_bug_module.tgz | 1.16 KB | rfay |
#1 | drupal.db_write_record_exception.patch | 3.77 KB | rfay |
Comments
Comment #1
rfayThe patch got lost off that one. Here it is.
Comment #2
rfayHere's the promised demonstration module. Seems it got lost as well. Not that you probably need it to study this patch.
Comment #3
Crell CreditAttribution: Crell commentedI think this makes sense. The bot agrees.
Comment #4
realityloop#1: drupal.db_write_record_exception.patch queued for re-testing.
Comment #6
jbrown CreditAttribution: jbrown commentedI think this function could be implemented in a simpler manner by combining with #755856: Don't insert default values into db in drupal_write_record()
It isn't necessary to use a gigantic try/catch.
$object only needs to be modified when inserting (the serial field and the default values) - this can be done at the end. The bulk of the work could be done on a copy of $object that is cast as an object.
I'll write a patch next week.
Comment #7
rfay@jbrown, if you're going to knock something out of RTBC you have to follow through with the better patch :-)
Comment #8
jbrown CreditAttribution: jbrown commentedokay - new patch at #755856: Don't insert default values into db in drupal_write_record() solves this problem without using try/catch
Comment #9
jbrown CreditAttribution: jbrown commentedComment #10
rfayThis one has been rolled into [#755866], which is currently RTBC.
Comment #11
jbrown CreditAttribution: jbrown commentedYou mean #755856: Don't insert default values into db in drupal_write_record().