#29182: SQLite database migration breaks ForeignKey constraint, leaving
<table_name>__old in db schema
-------------------------------------+-------------------------------------
Reporter: ezaquarii | Owner: nobody
Type: | Status: new
Uncategorized |
Component: | Version: 2.0
Migrations |
Severity: Normal | Keywords: sqlite migration
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
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.
This happens only when running SQLite DB migrations from management
command.
Running migrations via `./manage.py migrate` does not cause any issues.
This is the demonstration:
https://github.com/ezaquarii/openvpn-at-home/tree/sqlite-migration-bug
Steps to reproduce the bug
1. build the project with `make devel`
2. enter Python virtualenv by `source backend/env/bin/activate` and enter
`backend` subdirectory
3. run `./manage.py bootstrap` to initialize the database
4. bootstrap command runs db migration by calling
`call_command('migrate')` in
`openvpnathome/apps/management/management/commands/bootstrap.py:37`:
- `openvpn_server` table is created
- `openvpn_client` table is created; it uses foreign key to
`openvpn_server`
- another `openvpn_server` migration is run, adding dummy field
- `openvpn_server` table is renamed to `openvpn_server__old`
- `openvpn_client` foreign key is re-linked to `openvpn_server__old`
- new table `openvpn_server` is created and data from
`openvpn_server__old` is copied with applied alterations
- `openvpn_server__old` is dropped
- `openvpn_client` still references `openvpn_sever__old` - ForeignKey
constraint is **not** updated and DB is left in unusable state
6. try creating `Client` object in django shell - SQL cannot be executed
due to missing table
Exact commands (available in provided `bug_repro.sh` script):
{{{
make devel
cd backend
source ./env/bin/activate
./manage.py bootstrap
echo '
Now type that:
./manage.py shell
In [1]: from openvpnathome.apps.openvpn.models import Server, Client
In [2]: Client.objects.create()
... snip ...
OperationalError: no such table: main.openvpn_server__old
'
}}}
Exported database schema clearly references deleted `openvpn_server__old`
table:
{{{
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);
}}}
Please refer to `db_schema.sql` file placed in the `backend` subdirectory.
--
Ticket URL: <https://code.djangoproject.com/ticket/29182>
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.2c20ce961fadeb6c9cd3d18bba23281e%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.