Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #2272 -- Improved SQLite database introspection. Thanks, dne@ma…

…yonnaise.net

git-svn-id: http://code.djangoproject.com/svn/django/trunk@3285 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 49e5f5450d732a5d08c21c7e712e1728c6e635ce 1 parent 84dda19
Adrian Holovaty authored July 07, 2006
1  AUTHORS
@@ -54,6 +54,7 @@ answer newbie questions, and generally made Django that much better:
54 54
     Jason Davies (Esaj) <http://www.jasondavies.com/>
55 55
     Alex Dedul
56 56
     deric@monowerks.com
  57
+    dne@mayonnaise.net
57 58
     Jeremy Dunck <http://dunck.us/>
58 59
     Clint Ecker
59 60
     gandalf@owca.info
46  django/db/backends/sqlite3/introspection.py
@@ -2,18 +2,56 @@
2 2
 from django.db.backends.sqlite3.base import quote_name
3 3
 
4 4
 def get_table_list(cursor):
5  
-    cursor.execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name")
  5
+    "Returns a list of table names in the current database."
  6
+    # Skip the sqlite_sequence system table used for autoincrement key
  7
+    # generation.
  8
+    cursor.execute("""
  9
+        SELECT name FROM sqlite_master
  10
+        WHERE type='table' AND NOT name='sqlite_sequence'
  11
+        ORDER BY name""")
6 12
     return [row[0] for row in cursor.fetchall()]
7 13
 
8 14
 def get_table_description(cursor, table_name):
9  
-    cursor.execute("PRAGMA table_info(%s)" % quote_name(table_name))
10  
-    return [(row[1], row[2], None, None) for row in cursor.fetchall()]
  15
+    "Returns a description of the table, with the DB-API cursor.description interface."
  16
+    return [(info['name'], info['type'], None, None, None, None,
  17
+             info['null_ok']) for info in _table_info(cursor, table_name)]
11 18
 
12 19
 def get_relations(cursor, table_name):
13 20
     raise NotImplementedError
14 21
 
15 22
 def get_indexes(cursor, table_name):
16  
-    raise NotImplementedError
  23
+    """
  24
+    Returns a dictionary of fieldname -> infodict for the given table,
  25
+    where each infodict is in the format:
  26
+        {'primary_key': boolean representing whether it's the primary key,
  27
+         'unique': boolean representing whether it's a unique index}
  28
+    """
  29
+    indexes = {}
  30
+    for info in _table_info(cursor, table_name):
  31
+        indexes[info['name']] = {'primary_key': info['pk'] != 0,
  32
+                                 'unique': False}
  33
+    cursor.execute('PRAGMA index_list(%s)' % quote_name(table_name))
  34
+    # seq, name, unique
  35
+    for index, unique in [(field[1], field[2]) for field in cursor.fetchall()]:
  36
+        if not unique:
  37
+            continue
  38
+        cursor.execute('PRAGMA index_info(%s)' % quote_name(index))
  39
+        info = cursor.fetchall()
  40
+        # Skip indexes across multiple fields
  41
+        if len(info) != 1:
  42
+            continue
  43
+        name = info[0][2] # seqno, cid, name
  44
+        indexes[name]['unique'] = True
  45
+    return indexes
  46
+
  47
+def _table_info(cursor, name):
  48
+    cursor.execute('PRAGMA table_info(%s)' % quote_name(name))
  49
+    # cid, name, type, notnull, dflt_value, pk
  50
+    return [{'name': field[1],
  51
+             'type': field[2],
  52
+             'null_ok': not field[3],
  53
+             'pk': field[5]     # undocumented
  54
+             } for field in cursor.fetchall()]
17 55
 
18 56
 # Maps SQL types to Django Field types. Some of the SQL types have multiple
19 57
 # entries here because SQLite allows for anything and doesn't normalize the
5  docs/django-admin.txt
@@ -126,8 +126,9 @@ you run it, you'll want to look over the generated models yourself to make
126 126
 customizations. In particular, you'll need to rearrange models' order, so that
127 127
 models that refer to other models are ordered properly.
128 128
 
129  
-Primary keys are automatically introspected for PostgreSQL and MySQL, in which
130  
-case Django puts in the ``primary_key=True`` where needed.
  129
+Primary keys are automatically introspected for PostgreSQL, MySQL and
  130
+SQLite, in which case Django puts in the ``primary_key=True`` where
  131
+needed.
131 132
 
132 133
 ``inspectdb`` works with PostgreSQL, MySQL and SQLite. Foreign-key detection
133 134
 only works in PostgreSQL and with certain types of MySQL tables.

0 notes on commit 49e5f54

Please sign in to comment.
Something went wrong with that request. Please try again.