#36170: Running no-op migrations (verbose_name, ...) slow on sqlite
--------------------------------------+------------------------------------
     Reporter:  Klaas van Schelven    |                    Owner:  (none)
         Type:  Cleanup/optimization  |                   Status:  new
    Component:  Migrations            |                  Version:  5.1
     Severity:  Normal                |               Resolution:
     Keywords:                        |             Triage Stage:  Accepted
    Has patch:  0                     |      Needs documentation:  0
  Needs tests:  0                     |  Patch needs improvement:  0
Easy pickings:  0                     |                    UI/UX:  0
--------------------------------------+------------------------------------
Changes (by Simon Charette):

 * stage:  Unreviewed => Accepted

Comment:

 Interesting use case. I think it's worth a shot but we should definitely
 error on the side of caution here as to avoid causing subtle integrity
 violation regressions. That is the `PRAGMA foreign_key_check` might be
 necessary for other operations that SQLite added support for over the
 years such as `ADD FIELD` assuming it's a foreign key that can be
 populated with invalid data.

 I believe the following should cover all no-op migrations while avoiding
 the daunting task of figuring out for which operations are safe to skip
 foreign key checks for

 {{{#!diff
 diff --git a/django/db/backends/sqlite3/schema.py
 b/django/db/backends/sqlite3/schema.py
 index 3617d17fac..a74c010384 100644
 --- a/django/db/backends/sqlite3/schema.py
 +++ b/django/db/backends/sqlite3/schema.py
 @@ -33,13 +33,23 @@ def __enter__(self):
                  "SQLite does not support disabling them in the middle of
 "
                  "a multi-statement transaction."
              )
 +        # Avoid checking foreign key constraint for no-op migrations that
 +        # don't execute SQL as it can be expensive on large databases.
 +        self.must_check_constraints = False
          return super().__enter__()

      def __exit__(self, exc_type, exc_value, traceback):
 -        self.connection.check_constraints()
 +        if self.must_check_constraints:
 +            self.connection.check_constraints()
          super().__exit__(exc_type, exc_value, traceback)
          self.connection.enable_constraint_checking()

 +    def execute(self, *args, **kwargs):
 +        # Execution of any SQL results in a subsequent foreign key
 constraint
 +        # check to account for them being disabled during schema
 alteration.
 +        self.must_check_constraints = True
 +        return super().execute(*args, **kwargs)
 +
      def quote_value(self, value):
          # The backend "mostly works" without this function and there are
 use
          # cases for compiling Python without the sqlite3 libraries (e.g.
 }}}

 Does that sound like a reasonable compromise?
-- 
Ticket URL: <https://code.djangoproject.com/ticket/36170#comment:2>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/django-updates/01070194d3a799fc-ee0edd0f-1ebb-4dc0-a33d-a62f58bb04f9-000000%40eu-central-1.amazonses.com.

Reply via email to