475
475
cr = pooler.get_db(db).cursor()
477
# We autocommit: our single request will be performed atomically.
477
# autocommit: our single request will be performed atomically.
478
478
# (In this way, there is no opportunity to have two transactions
479
# interleaving ther cr.execute()..cr.commit() calls and have one
480
# of them rollbacked due to a concurrent access.)
479
# interleaving their cr.execute()..cr.commit() calls and have one
480
# of them rolled back due to a concurrent access.)
481
481
# We effectively unconditionally write the res_users line.
482
482
cr.autocommit(True)
483
# Even w/ autocommit there's a chance the user row will be locked,
484
# in which case we can't delay the login just for the purpose of
485
# update the last login date - hence we use FOR UPDATE NOWAIT to
486
# try to get the lock - fail-fast
487
cr.execute("""SELECT id from res_users
488
WHERE login=%s AND password=%s
489
AND active FOR UPDATE NOWAIT""",
490
(tools.ustr(login), tools.ustr(password)))
483
491
cr.execute("""UPDATE res_users
484
492
SET date = now() AT TIME ZONE 'UTC'
485
WHERE login=%s AND password=%s AND active RETURNING id""",
486
(tools.ustr(login), tools.ustr(password)))
493
WHERE login=%s AND password=%s AND active
495
(tools.ustr(login), tools.ustr(password)))
497
# Failing to acquire the lock on the res_users row probably means
498
# another request is holding it. No big deal, we don't want to
499
# prevent/delay login in that case. It will also have been logged
500
# as a SQL error, if anyone cares.
501
cr.execute("""SELECT id from res_users
502
WHERE login=%s AND password=%s
504
(tools.ustr(login), tools.ustr(password)))
487
506
res = cr.fetchone()
495
512
def check_super(self, passwd):
496
513
if passwd == tools.config['admin_passwd']: