3

Got a big problem that's confusing as hell. I'm using Laravel (3.2.5 and now 3.2.7) and I'm using the Eloquent ORM for updating a database (PostgreSQL).

Here's what I'm doing:

  • I have a db full of data
  • I'm pulling info from an external API to update my db full of data
  • I run a script that puts the db full of data into arrays and same with API. This gets compared
  • I fill a data object with an array full of changes
  • I "save" it
  • nothing happens -.-
    $updateLinks = array_diff($dbLinkArray, $dbLinkArrayOriginal);

    $dbLink->fill($updateLinks);

    Log::info('1st LOG Original: '.$dbLinkArrayOriginal['link_text'].' New: '.$dbLinkArray['link_text']);

    Log::info('2nd Log Dirty: '.implode(', ', $dbLink->get_dirty()));

    $dbLink->save();

    Log::info('3rd Log Supposed to be changed: '.implode(', ',array_keys($updateLinks)));

I employed some logging and the debug toolbar to figure out wtf happened. Here's the info:

  • all the SQL queries run to update with correct information. When the Query is run via phpPgAdmin, it updates as it should. The problem here is that the query updates EVERY column in the row instead of just the changes. Using "update" instead of "fill/save" creates the same problem.
  • none of the table information gets updated, ever.
  • The 1st log shows that the link_text isn't equal. This is okay because it shows the link_text needs to be updated. However, it's a clear indicator that nothing was updated the next time I run my script. The log shows the same info every time and just as many log events happen.
  • The 2nd log shows that the ENTIRE object is dirty rather than just what was supposed to be updated. This is why the SQL gets updated
  • The 3rd log spits out exactly what's supposed to be updated. 3-5 columns max and that's it. And all is in correct format.

Any idea why, first of all, the database is not getting updated even though Laravel marks the SQL as being run and shows the correct query?

Also, any idea why the ENTIRE object is dirty and the query tries to update the entire object (23+ columns) instead of only the changes (3-5 columns)?

The Alpha
  • 143,660
  • 29
  • 287
  • 307
antjanus
  • 987
  • 3
  • 15
  • 30
  • The 1st issue sounds like autocommit/transaction issues. Are you committing the work? – Craig Ringer Sep 04 '12 at 14:09
  • As far as I'm aware Laravel does this automatically; however, I may be wrong. How would you commit an update? And would you do it after every SQL query or after the entire script is done? Also good catch. Didn't even think of it, just assumed Laravel would do that automatically. – antjanus Sep 04 '12 at 14:15
  • No idea, I don't do PHP and don't know what Laravel is beyond the tag description. Issues with transactions not being committed is just a common cause of "SQL runs but data doesn't appear in database" problems. Maybe enable `log_statement='all'` and `log_line_prefix='%d %p'` in `postgresql.conf` and see if you can find `BEGIN`s without matching `COMMIT`s in the logs? Or look at `pg_stat_activity` and see if there are ` in transaction` entries? Their presence strongly suggests dangling transactions; their absence doesn't rule them out, only log examination will do that. – Craig Ringer Sep 04 '12 at 22:02

1 Answers1

2

For your second question (why all columns update, instead of just the dirty ones). The Laravel documentation states:

By default, all attribute key/value pairs will be store during mass-assignment. However, it is possible to create a white-list of attributes that will be set. If the accessible attribute white-list is set then no attributes other than those specified will be set during mass-assignment.

Does this help you?

Kind regards, Hendrik

Hendrik Jan
  • 4,396
  • 8
  • 39
  • 75