#23379: sql_create generates incorrect SQL with synced database
----------------------------------------------+----------------------
     Reporter:  flakfizer                     |      Owner:  nobody
         Type:  Bug                           |     Status:  new
    Component:  Database layer (models, ORM)  |    Version:  1.7-rc-3
     Severity:  Normal                        |   Keywords:
 Triage Stage:  Unreviewed                    |  Has patch:  1
Easy pickings:  0                             |      UI/UX:  0
----------------------------------------------+----------------------
 The change between 1.6.6 to 1.7c3 in sql_create's first parameter from
 "app" to "app_config" is causing a bug, namely because app.get_models()
 returned a list, whereas app_config.get_models() returns a generator.
 This causes the "known_models" set to be larger than it should be.

 This bug will cause invalid sql - mysql, in my case - to be generated if
 tables already exist, as shown in the attached reproduction app.

 1) python manage.py repro  # generates correct sql

 CREATE TABLE `repro_app_a` (
     `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
     `b_id` integer NOT NULL
 )
 ;
 CREATE TABLE `repro_app_b` (
     `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
     `a_id` integer NOT NULL
 )
 ;
 ALTER TABLE `repro_app_b` ADD CONSTRAINT `a_id_refs_id_4838e71a` FOREIGN
 KEY (`a_id`) REFERENCES `repro_app_a` (`id`);
 ALTER TABLE `repro_app_a` ADD CONSTRAINT `b_id_refs_id_b49a3179` FOREIGN
 KEY (`b_id`) REFERENCES `repro_app_b` (`id`);

 2) python manage.py migrate
 3) python manage.py repro  # generates incorrect sql; the first constraint
 fails because table repro_app_b hasn't been created yet.

 CREATE TABLE `repro_app_a` (
     `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
     `b_id` integer NOT NULL
 )
 ;
 ALTER TABLE `repro_app_a` ADD CONSTRAINT `b_id_refs_id_b49a3179` FOREIGN
 KEY (`b_id`) REFERENCES `repro_app_b` (`id`);
 CREATE TABLE `repro_app_b` (
     `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
     `a_id` integer NOT NULL
 )
 ;
 ALTER TABLE `repro_app_b` ADD CONSTRAINT `a_id_refs_id_4838e71a` FOREIGN
 KEY (`a_id`) REFERENCES `repro_app_a` (`id`);


 Fortunately, the (or, "a") fix is an easy one-liner:

 diff --git a/django/core/management/sql.py b/django/core/management/sql.py
 index 323cb54..048b051 100644
 --- a/django/core/management/sql.py
 +++ b/django/core/management/sql.py
 @@ -36,7 +36,7 @@ def sql_create(app_config, style, connection):
      # We trim models from the current app so that the sqlreset command
 does not
      # generate invalid SQL (leaving models out of known_models is
 harmless, so
      # we can be conservative).
 -    app_models = app_config.get_models(include_auto_created=True)
 +    app_models = set(app_config.get_models(include_auto_created=True))
      final_output = []
      tables = connection.introspection.table_names()
      known_models = set(model for model in
 connection.introspection.installed_models(tables) if model not in
 app_models)

--
Ticket URL: <https://code.djangoproject.com/ticket/23379>
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 post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/052.4204cdda2655bbe9f866f533fd60d866%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to