[IMP] base: safer locking at user login
authorMartin Trigaux <mat@openerp.com>
Mon, 22 Sep 2014 15:56:51 +0000 (17:56 +0200)
committerMartin Trigaux <mat@openerp.com>
Mon, 22 Sep 2014 16:18:41 +0000 (18:18 +0200)
When a users connects, a lock is taken on the res_user table to modify the last login date. If another running transaction uses a foreign key to res.users (e.g. write_uid column), postgres may detect the update as a concurrent update and rollback the transaction.
In pg 9.3, the lock_strength parameter 'NO KEY' allows a weaker lock which is less likely to break another transaction.
Fixes #552

openerp/addons/base/res/res_users.py

index a0e0bd1..eeca380 100644 (file)
@@ -435,7 +435,9 @@ class res_users(osv.osv):
                 # prevent/delay login in that case. It will also have been logged
                 # as a SQL error, if anyone cares.
                 try:
-                    cr.execute("SELECT id FROM res_users WHERE id=%s FOR UPDATE NOWAIT", (user_id,), log_exceptions=False)
+                    # NO KEY introduced in PostgreSQL 9.3 http://www.postgresql.org/docs/9.3/static/release-9-3.html#AEN115299
+                    update_clause = 'NO KEY UPDATE' if cr._cnx.server_version >= 90300 else 'UPDATE'
+                    cr.execute("SELECT id FROM res_users WHERE id=%%s FOR %s NOWAIT" % update_clause, (user_id,), log_exceptions=False)
                     cr.execute("UPDATE res_users SET login_date = now() AT TIME ZONE 'UTC' WHERE id=%s", (user_id,))
                     self.invalidate_cache(cr, user_id, ['login_date'], [user_id])
                 except Exception: