#29350 closed Bug (fixed)
Sqlite3 Introspection (get_primary_key_column) Always Returns None
| Reported by: | Zackary Troop | Owned by: | Zackary Troop |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 2.0 |
| Severity: | Normal | Keywords: | sqlite3 |
| Cc: | Triage Stage: | Ready for checkin | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Hello, I've noticed that the get_primary_key_column method always returns None, even though a Primary Key is present in the table. I am using the sqlite3 backend. I've captured the steps to reproduce below.
Create new environment, install Django.
(env) system :: ~/OpenSource/testing % pip3 install django
Collecting django
Downloading https://files.pythonhosted.org/packages/89/f9/94c20658f0cdecc2b6607811e2c0bb042408a51f589e5ad0cb0eac3236a1/Django-2.0.4-py3-none-any.whl (7.1MB)
100% |████████████████████████████████| 7.1MB 504kB/s
Collecting pytz (from django)
Downloading https://files.pythonhosted.org/packages/dc/83/15f7833b70d3e067ca91467ca245bae0f6fe56ddc7451aa0dc5606b120f2/pytz-2018.4-py2.py3-none-any.whl (510kB)
100% |████████████████████████████████| 512kB 694kB/s
Installing collected packages: pytz, django
Successfully installed django-2.0.4 pytz-2018.4
Create new sqlite3 database called test.sqlite3 and add a new table with a Primary Key.
(env) system :: OpenSource/testing/testapp % sqlite3 test.sqlite3 SQLite version 3.23.1 2018-04-10 17:39:29 Enter ".help" for usage hints. sqlite> CREATE TABLE `food` ( ...> id int PRIMARY KEY NOT NULL, ...> food_group_id int REFERENCES food_group(id) NOT NULL, ...> long_desc text NOT NULL DEFAULT '', ...> short_desc text NOT NULL DEFAULT '' ...> ); sqlite> .exit
Add database profile to settings.
(env) system :: OpenSource/testing/testapp % nano testapp/settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
},
'testdb': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'test.sqlite3'),
}
}
Open Django shell, verify table existance and try to determine if a Primary Key is present.
(env) system :: OpenSource/testing/testapp % python manage.py shell >>> from django.db import connections >>> from django.db.backends.sqlite3 import introspection >>> db_conn = connections['testdb'] >>> cur = db_conn.cursor() >>> introspection.DatabaseIntrospection(db_conn).get_table_list(cur) [TableInfo(name='food', type='t')] >>> answer = introspection.DatabaseIntrospection(db_conn).get_primary_key_column(cur, 'food') >>> type(answer) <class 'NoneType'>
Change History (7)
comment:1 by , 8 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:2 by , 8 years ago
Small tweak in the introspection.py in the sqlite3 backend will fix this. I can setup the PR tonight.
>>> for field_desc in fields_sql.split(','):
... field_desc = field_desc.strip()
... m = re.match(r"(\w+).*PRIMARY KEY(?: AUTOINCREMENT)?.*", field_desc)
... if m:
... print(m.group(1))
...
id
comment:3 by , 8 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
comment:5 by , 8 years ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
Looks like the regex used by Django to detect the primary key expects a quoted column name, which is not always the case for legacy tables.