Changes between Version 3 and Version 4 of Ticket #29182
- Timestamp:
- Mar 3, 2018, 2:20:30 PM (7 years ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
Ticket #29182 – Description
v3 v4 1 1 SQLite table alteration uses rename and copy method. When running a database migration from Django command (via `call_command('migrate')`), database is left with references to <table_name>__old table that has been dropped after migration. 2 2 3 This happens only when running SQLite DB migrations from management command .3 This happens only when running SQLite DB migrations from management command under transaction. 4 4 Running migrations via `./manage.py migrate` does not cause any issues. 5 5 6 6 This is the demonstration: 7 https://github.com/ezaquarii/ openvpn-at-home/tree/sqlite-migration-bug7 https://github.com/ezaquarii/django-sqlite-migration-bug 8 8 9 9 Steps to reproduce the bug 10 1. build the project with `make devel` 10 1. run ./bootstrap.sh 11 2. from import app.models import * 12 3. Bravo.objects.create() 13 4. SQL cannot be executed due to missing table `main.app_alpha__old` 11 14 12 2. enter Python virtualenv by `source backend/env/bin/activate` and enter `backend` subdirectory 13 14 3. run `./manage.py bootstrap` to initialize the database 15 16 4. bootstrap command runs db migration by calling `call_command('migrate')` in `openvpnathome/apps/management/management/commands/bootstrap.py:37`: 17 - `openvpn_server` table is created 18 - `openvpn_client` table is created; it uses foreign key to `openvpn_server` 19 - another `openvpn_server` migration is run, adding dummy field 20 - `openvpn_server` table is renamed to `openvpn_server__old` 21 - `openvpn_client` foreign key is re-linked to `openvpn_server__old` 22 - new table `openvpn_server` is created and data from `openvpn_server__old` is copied with applied alterations 23 - `openvpn_server__old` is dropped 24 - `openvpn_client` still references `openvpn_sever__old` - ForeignKey constraint is **not** updated and DB is left in unusable state 25 6. try creating `Client` object in django shell - SQL cannot be executed due to missing table 15 - `app/management/commands/bootstrap.py:9`: run the migration 16 - `alpha` table is created 17 - `bravo` table is created; it uses foreign key to `alpha` 18 - another `alpha` migration is run, adding dummy field 19 - `alpha` table is renamed to `alpha__old` 20 - `bravo` foreign key is re-linked to `alpha__old` 21 - new table `alpha` is created and data from `alpha__old` is copied with applied alterations 22 - `alpha__old` is dropped 23 - `bravo` still references `alpha__old` - ForeignKey constraint is **not** updated and DB is left in unusable state 26 24 27 25 28 Exact commands (available in provided `bug_repro.sh` script):29 26 {{{ 30 cd backend 31 make devel 32 source ./env/bin/activate 33 ./manage.py bootstrap 34 35 echo ' 36 Now type that: 37 38 ./manage.py shell 39 In [1]: from openvpnathome.apps.openvpn.models import Server, Client 40 41 In [2]: Client.objects.create() 42 43 ... snip ... 44 45 OperationalError: no such table: main.openvpn_server__old 46 ' 27 CREATE TABLE "app_bravo" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "dummy" varchar(10) NOT NULL, "alpha_id" integer NOT NULL REFERENCES "app_alpha__old" ("id") DEFERRABLE INITIALLY DEFERRED); 47 28 }}} 48 29 49 Exported database schema clearly references deleted `openvpn_server__old` table:50 51 {{{52 CREATE TABLE "openvpn_client" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "created" datetime NOT NULL, "name" varchar(64) NOT NULL, "cert_id" integer NOT NULL REFERENCES "x509_cert" ("id") DEFERRABLE INITIALLY DEFERRED, "owner_id" integer NOT NULL REFERENCES "accounts_user" ("id") DEFERRABLE INITIALLY DEFERRED, "server_id" integer NOT NULL REFERENCES "openvpn_server__old" ("id") DEFERRABLE INITIALLY DEFERRED);53 }}}54 55 Please refer to `db_schema.sql` file placed in the `backend` subdirectory.56 57 30 Tested with Django versions: 2.0.1 and 2.0.2