Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django1.6, will transaction works for raw SQL?

Examples from offical document

from django.db import connection

def my_custom_sql(self):
    cursor = connection.cursor()

    cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])

    cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
    row = cursor.fetchone()

    return row

if update will affect select, for example

cursor.execute("UPDATE bar SET foo = foo + 1 WHERE baz = %s", [self.baz])
cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])

Does transaction works for raw SQL, like this snap code works?

from django.db import connection, transaction

def my_custom_sql(self):
    try:
        with transaction.atomic():
            cursor = connection.cursor()
            cursor.execute("UPDATE bar SET foo = foo + 1 WHERE baz = %s", [self.baz])
            cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
            row = cursor.fetchone()
            return row
    except IntegrityError:
        transaction.rollback()

Or the for the first code, begin cursor already start a transaction?

like image 498
linbo Avatar asked Nov 02 '22 09:11

linbo


1 Answers

I can see only sanity checks with self.db.validate_no_broken_transaction() here:

def execute(self, sql, params=None):
    self.db.validate_no_broken_transaction()
    self.db.set_dirty()
    with self.db.wrap_database_errors:
        if params is None:
            return self.cursor.execute(sql)
        else:
            return self.cursor.execute(sql, params)

So the answer is no, cursor doesn't wrap raw SQL in transaction by default.

Update:

If you need transactions and ATOMIC_REQUESTS = False you can use transaction.atomic() like decorator or context manager.

NB: django.db.connection is there only for backwards comnatibility. You should use django.db.connections['default'] or even better

from django.db import DEFAULT_DB_ALIAS

def get_connection(using=None):
    """
    Get a database connection by name, or the default database connection
    if no name is provided.
    """
    if using is None:
        using = DEFAULT_DB_ALIAS
    return connections[using]

like here

like image 92
twil Avatar answered Nov 15 '22 04:11

twil