#24533: Changing an AutoField into an IntegerField leaks the sequence on 
PostgreSQL
--------------------------------------+------------------------
               Reporter:  aaugustin   |          Owner:  nobody
                   Type:  Bug         |         Status:  new
              Component:  Migrations  |        Version:  1.7
               Severity:  Normal      |       Keywords:
           Triage Stage:  Unreviewed  |      Has patch:  0
    Needs documentation:  0           |    Needs tests:  0
Patch needs improvement:  0           |  Easy pickings:  0
                  UI/UX:  0           |
--------------------------------------+------------------------
 '''Step 1'''

 Create the following model:

 {{{
 class TestId(models.Model):
     pass
 }}}

 Create migrations:

 {{{
 % ./manage.py makemigrations test_id
 Migrations for 'test_id':
   0001_initial.py:
     - Create model TestId
 % ./manage.py sqlmigrate test_id 0001
 BEGIN;
 CREATE TABLE "test_id_testid" ("id" serial NOT NULL PRIMARY KEY);

 COMMIT;
 % ./manage.py migrate test_id 0001
 Operations to perform:
   Target specific migration: 0001_initial, from test_id
 Running migrations:
   Applying test_id.0001_initial... OK
 }}}

 '''Step 2'''

 Change the primary key from an AutoField to an IntegerField:

 {{{
 class TestId(models.Model):
     id = models.IntegerField(primary_key=True)
 }}}

 Create migrations:

 {{{
 % ./manage.py makemigrations test_id
 Migrations for 'test_id':
   0002_auto_20150324_2107.py:
     - Alter field id on testid
 % ./manage.py sqlmigrate test_id 0002
 BEGIN;
 ALTER TABLE "test_id_testid" ALTER COLUMN "id" TYPE integer;

 COMMIT;
 % ./manage.py migrate test_id 0002
 Operations to perform:
   Target specific migration: 0002_auto_20150324_2107, from test_id
 Running migrations:
   Applying test_id.0002_auto_20150324_2107... OK
 }}}

 At this point the database contains an unused sequence:

 {{{
 --
 -- Name: test_id_testid_id_seq; Type: SEQUENCE; Schema: public; Owner:
 oshop
 --

 CREATE SEQUENCE test_id_testid_id_seq
     START WITH 1
     INCREMENT BY 1
     NO MINVALUE
     NO MAXVALUE
     CACHE 1;


 ALTER TABLE public.test_id_testid_id_seq OWNER TO oshop;

 --
 -- Name: test_id_testid_id_seq; Type: SEQUENCE OWNED BY; Schema: public;
 Owner: oshop
 --

 ALTER SEQUENCE test_id_testid_id_seq OWNED BY test_id_testid.id;
 }}}

 '''Step 3''

 Fortunately, if you revert to an `AutoField`:

 {{{
 class TestId(models.Model):
     pass
 }}}

 and recreate migrations, the sequence is dropped and recreated, avoiding a
 crash:

 {{{
 % ./manage.py makemigrations test_id
 Migrations for 'test_id':
   0003_auto_20150324_2109.py:
     - Alter field id on testid
 % ./manage.py sqlmigrate test_id 0003
 BEGIN;
 ALTER TABLE "test_id_testid" ALTER COLUMN "id" TYPE integer;
 DROP SEQUENCE IF EXISTS test_id_testid_id_seq CASCADE;
 CREATE SEQUENCE test_id_testid_id_seq;
 ALTER TABLE test_id_testid ALTER COLUMN id SET DEFAULT
 nextval('test_id_testid_id_seq');
 SELECT setval('test_id_testid_id_seq', MAX(id)) FROM test_id_testid;

 COMMIT;
 % ./manage.py migrate test_id 0003
 Operations to perform:
   Target specific migration: 0003_auto_20150324_2109, from test_id
 Running migrations:
   Applying test_id.0003_auto_20150324_2109... OK
 }}}

 Is it possible to drop the sequence at step 2 rather than step 3?

 That way, users will get the same database schema regardless of whether
 they've squashed migrations. Indeeed, after squashing migrations 1 and 2,
 the extra sequence isn't created.

--
Ticket URL: <https://code.djangoproject.com/ticket/24533>
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.15aa85ee178707b94e68f2e341c1a2e0%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to