From 49e5f5450d732a5d08c21c7e712e1728c6e635ce Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Fri, 7 Jul 2006 04:06:00 +0000 Subject: [PATCH] Fixed #2272 -- Improved SQLite database introspection. Thanks, dne@mayonnaise.net git-svn-id: http://code.djangoproject.com/svn/django/trunk@3285 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- AUTHORS | 1 + django/db/backends/sqlite3/introspection.py | 46 +++++++++++++++++++-- docs/django-admin.txt | 5 ++- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/AUTHORS b/AUTHORS index a7ce5c488a..d34e882494 100644 --- a/AUTHORS +++ b/AUTHORS @@ -54,6 +54,7 @@ answer newbie questions, and generally made Django that much better: Jason Davies (Esaj) Alex Dedul deric@monowerks.com + dne@mayonnaise.net Jeremy Dunck Clint Ecker gandalf@owca.info diff --git a/django/db/backends/sqlite3/introspection.py b/django/db/backends/sqlite3/introspection.py index c5fa738249..cdabffdc1c 100644 --- a/django/db/backends/sqlite3/introspection.py +++ b/django/db/backends/sqlite3/introspection.py @@ -2,18 +2,56 @@ from django.db import transaction from django.db.backends.sqlite3.base import quote_name def get_table_list(cursor): - cursor.execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name") + "Returns a list of table names in the current database." + # Skip the sqlite_sequence system table used for autoincrement key + # generation. + cursor.execute(""" + SELECT name FROM sqlite_master + WHERE type='table' AND NOT name='sqlite_sequence' + ORDER BY name""") return [row[0] for row in cursor.fetchall()] def get_table_description(cursor, table_name): - cursor.execute("PRAGMA table_info(%s)" % quote_name(table_name)) - return [(row[1], row[2], None, None) for row in cursor.fetchall()] + "Returns a description of the table, with the DB-API cursor.description interface." + return [(info['name'], info['type'], None, None, None, None, + info['null_ok']) for info in _table_info(cursor, table_name)] def get_relations(cursor, table_name): raise NotImplementedError def get_indexes(cursor, table_name): - raise NotImplementedError + """ + Returns a dictionary of fieldname -> infodict for the given table, + where each infodict is in the format: + {'primary_key': boolean representing whether it's the primary key, + 'unique': boolean representing whether it's a unique index} + """ + indexes = {} + for info in _table_info(cursor, table_name): + indexes[info['name']] = {'primary_key': info['pk'] != 0, + 'unique': False} + cursor.execute('PRAGMA index_list(%s)' % quote_name(table_name)) + # seq, name, unique + for index, unique in [(field[1], field[2]) for field in cursor.fetchall()]: + if not unique: + continue + cursor.execute('PRAGMA index_info(%s)' % quote_name(index)) + info = cursor.fetchall() + # Skip indexes across multiple fields + if len(info) != 1: + continue + name = info[0][2] # seqno, cid, name + indexes[name]['unique'] = True + return indexes + +def _table_info(cursor, name): + cursor.execute('PRAGMA table_info(%s)' % quote_name(name)) + # cid, name, type, notnull, dflt_value, pk + return [{'name': field[1], + 'type': field[2], + 'null_ok': not field[3], + 'pk': field[5] # undocumented + } for field in cursor.fetchall()] # Maps SQL types to Django Field types. Some of the SQL types have multiple # entries here because SQLite allows for anything and doesn't normalize the diff --git a/docs/django-admin.txt b/docs/django-admin.txt index 3334ae4530..04d86aa3b4 100644 --- a/docs/django-admin.txt +++ b/docs/django-admin.txt @@ -126,8 +126,9 @@ you run it, you'll want to look over the generated models yourself to make customizations. In particular, you'll need to rearrange models' order, so that models that refer to other models are ordered properly. -Primary keys are automatically introspected for PostgreSQL and MySQL, in which -case Django puts in the ``primary_key=True`` where needed. +Primary keys are automatically introspected for PostgreSQL, MySQL and +SQLite, in which case Django puts in the ``primary_key=True`` where +needed. ``inspectdb`` works with PostgreSQL, MySQL and SQLite. Foreign-key detection only works in PostgreSQL and with certain types of MySQL tables.