I'm trying to convert some raw DBI calls to DBIx::Class. I occasionally run across something like:
UPDATE 'foo' SET bar = bar + 1 WHERE ...
Is there way to do have DBIx::Class execute exactly this kind of query? I don't want to do something like:
$row->update({ bar => $row->bar() + 1 });
because there's a race condition there if multiple processes are trying to do the same thing.
I could get around that with some kind of locking at the database level, but that seems worse to me than just using the original query. Basically I just want to know if there's a clean way of using DBIC to do this or if I should just continue to use raw DBI calls here.
$row->{bar}
and not$row->bar()
– Turtleback$schema->resultset('Widget')->search({ name => 'foo' })->update_all({ count => \'count + 1' })
to add 1 tocount
wherename
isfoo
. This generates two SQL statements, but they're automatically wrapped in a transaction:SELECT me.id, me.name, me.count FROM test me WHERE ( name = 'foo' )
followed byUPDATE test SET count = count + 1 WHERE ( id = '1' )
– PhosphoproteinUPDATE
is generated for each row in the result set. Depending on your database engine, this may or may not be acceptable. With MySQL's InnoDB, for example, transactions are supported and the default transaction isolation level is repeatable read; all reads after the first use the same snapshot, so they won't be affected by later transactions. MySQL's MyISAM, on the other hand, doesn't support transactions, so you would still have a nasty race condition. – Phosphoprotein