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.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

rfay’s picture

The patch got lost off that one. Here it is.

rfay’s picture

Here's the promised demonstration module. Seems it got lost as well. Not that you probably need it to study this patch.

Crell’s picture

Status: Needs review » Reviewed & tested by the community

I think this makes sense. The bot agrees.

realityloop’s picture

Status: Reviewed & tested by the community » Needs work

The last submitted patch, drupal.db_write_record_exception.patch, failed testing.

jbrown’s picture

I 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.

rfay’s picture

@jbrown, if you're going to knock something out of RTBC you have to follow through with the better patch :-)

jbrown’s picture

okay - new patch at #755856: Don't insert default values into db in drupal_write_record() solves this problem without using try/catch

jbrown’s picture

Title: db_write_record() silently converts an array to an object in case of an exception » drupal_write_record() silently converts an array to an object in case of an exception
rfay’s picture

Status: Needs work » Closed (duplicate)

This one has been rolled into [#755866], which is currently RTBC.

jbrown’s picture