I am doing a bulk insert of records into a database from a log file. Occasionally (~1 row out of every thousand) one of the rows violates the primary key and causes the tran
You can do a rollback to the transaction or a rollback to a save point just before the code that raises the exception (cr is the cursor):
name = uuid.uuid1().hex
cr.execute('SAVEPOINT "%s"' % name)
try:
# your failing query goes here
except Exception:
cr.execute('ROLLBACK TO SAVEPOINT "%s"' % name)
# your alternative code goes here
else:
cr.execute('RELEASE SAVEPOINT "%s"' % name)
This code assumes there is running transaction, otherwise you would not receive that error message.
Django postgresql backend creates cursors directly from psycopg. Maybe in the future they make a proxy class for the Django cursor, similar to the cursor of odoo. They extend the cursor with the following code (self is the cursor):
@contextmanager
@check
def savepoint(self):
"""context manager entering in a new savepoint"""
name = uuid.uuid1().hex
self.execute('SAVEPOINT "%s"' % name)
try:
yield
except Exception:
self.execute('ROLLBACK TO SAVEPOINT "%s"' % name)
raise
else:
self.execute('RELEASE SAVEPOINT "%s"' % name)
That way the context makes your code easier, it will be:
try:
with cr.savepoint():
# your failing query goes here
except Exception:
# your alternative code goes here
and the code is more readable, because the transaction stuff is not there.