2014-11-07 9 views
6

Ich versuche einige rohe DBI-Aufrufe in DBIx :: Class zu konvertieren. Ich laufe hin und wieder über so etwas wie:Wie erhöht man eine Spalte mit DBIx :: Class?

UPDATE 'foo' SET bar = bar + 1 WHERE ... 

Gibt es Weise DBIx :: Klasse ausführen genau diese Art der Abfrage zu tun? Ich will nicht so etwas wie zu tun:

$row->update({ bar => $row->bar() + 1 }); 

, weil es eine Race-Bedingung ist es, wenn mehr Prozesse die gleiche Sache zu tun versuchen.

Ich könnte das mit einer Art von Sperren auf Datenbankebene umgehen, aber das scheint mir schlimmer als nur die ursprüngliche Abfrage verwenden. Im Grunde möchte ich nur wissen, ob es eine saubere Möglichkeit gibt, DBIC zu verwenden, oder ob ich einfach weiterhin rohe DBI-Aufrufe hier verwenden soll.

+0

Ich nehme an, Sie bedeuten '$ row -> {bar} 'und nicht' $ row-> bar() ' – TLP

+0

Increments by 1 ist normalerweise für Zähler. Welche Arten von Rennbedingungen erleben Sie in diesem Bereich? –

+0

@TLP Ich meinte $ row-> bar() wobei $ row ein DBIC-Ergebnisobjekt ist. – oalders

Antwort

3

Verwendung der Lösung von @ ThisSuitIsBlackNot Kommentar wickeln aber ersetzen update_all mit update:

$rs->search(...)->update({ 
    bar => \'bar + 1', 
}); 

Dies in einer einzigen Anweisung UPDATE führen. (Erläuterung:.. update_all Werke von update auf jeder Zeile in der ResultSet einschließlich solcher Dinge wie DBIC Auslöser nennen, so hat es die Zeilen zuerst holen update auf einem ResultSet führt einen Barebone-SQL UPDATE)

0

Wird DBIx :: Class :: Storage :: TxnScopeGuard helfen? Sie können Ihren Code-Block in einer Transaktion wie diese

my $guard = $schema->txn_scope_guard; 
# your increment 
$guard->commit; 
+1

In diesem Fall löst es das Problem nicht vollständig bei Lesezeit sowie Schreibzeit auftritt. Ich denke, der Kommentar von @ThisSuitIsBlackNot ist wahrscheinlich der sauberste Weg, dies zu tun. – oalders

+0

@oalders - ja, danke. –

Verwandte Themen