Django

Code

root/django/branches/schema-evolution/django/db/backends/sqlite3/introspection.py

Revision 5822, 5.3 kB (checked in by danderson, 1 year ago)

schema-evolution: update from HEAD (v5821)

Line 
1 from django.db.backends.sqlite3.base import quote_name
2
3 def get_table_list(cursor):
4     "Returns a list of table names in the current database."
5     # Skip the sqlite_sequence system table used for autoincrement key
6     # generation.
7     cursor.execute("""
8         SELECT name FROM sqlite_master
9         WHERE type='table' AND NOT name='sqlite_sequence'
10         ORDER BY name""")
11     return [row[0] for row in cursor.fetchall()]
12
13 def get_table_description(cursor, table_name):
14     "Returns a description of the table, with the DB-API cursor.description interface."
15     return [(info['name'], info['type'], None, None, None, None,
16              info['null_ok']) for info in _table_info(cursor, table_name)]
17
18 def get_relations(cursor, table_name):
19     raise NotImplementedError
20
21 def get_indexes(cursor, table_name):
22     """
23     Returns a dictionary of fieldname -> infodict for the given table,
24     where each infodict is in the format:
25         {'primary_key': boolean representing whether it's the primary key,
26          'unique': boolean representing whether it's a unique index}
27     """
28     indexes = {}
29     cursor.execute('PRAGMA index_list(%s)' % quote_name(table_name))
30     # seq, name, unique
31     for index, unique in [(field[1], field[2]) for field in cursor.fetchall()]:
32         if not unique:
33             continue
34         cursor.execute('PRAGMA index_info(%s)' % quote_name(index))
35         info = cursor.fetchall()
36         for x in info:
37             name = x[2] # seqno, cid, name
38             cursor.execute('PRAGMA table_info(%s)' % quote_name(table_name))
39             for row in cursor.fetchall():
40                 if row[1]==name:
41                     indexes[name] = {'primary_key': False, 'unique': False}
42                     if row[2]=='integer':
43                         indexes[name]['primary_key'] = True
44                     else:
45                         indexes[name]['unique'] = True
46     return indexes
47
48 def get_columns(cursor, table_name):
49     try:
50         cursor.execute("PRAGMA table_info(%s)" % quote_name(table_name))
51         return [row[1] for row in cursor.fetchall()]
52     except:
53         return []
54        
55 def get_known_column_flags( cursor, table_name, column_name ):
56     cursor.execute("PRAGMA table_info(%s)" % quote_name(table_name))
57     dict = {}
58     dict['primary_key'] = False
59     dict['foreign_key'] = False
60     dict['unique'] = False
61     dict['default'] = ''
62     dict['allow_null'] = True
63
64     for row in cursor.fetchall():
65 #        print row
66         if row[1] == column_name:
67             col_type = row[2]
68
69             # maxlength check goes here
70             if row[2][0:7]=='varchar':
71                 dict['maxlength'] = row[2][8:len(row[2])-1]
72            
73             # default flag check goes here
74             dict['allow_null'] = row[3]==0
75            
76             # default value check goes here
77             dict['default'] = row[4]
78
79     cursor.execute("PRAGMA index_list(%s)" % quote_name(table_name))
80     index_names = []
81     for row in cursor.fetchall():
82         index_names.append(row[1])
83     for index_name in index_names:
84         cursor.execute("PRAGMA index_info(%s)" % quote_name(index_name))
85         for row in cursor.fetchall():
86             if row[2]==column_name:
87                 if col_type=='integer': dict['primary_key'] = True  # sqlite3 does not distinguish between unique and pk; all
88                 else: dict['unique'] = True                         # unique integer columns are treated as part of the pk.
89
90             # primary/foreign/unique key flag check goes here
91             #if row[3]=='PRI': dict['primary_key'] = True
92             #else: dict['primary_key'] = False
93             #if row[3]=='FOR': dict['foreign_key'] = True
94             #else: dict['foreign_key'] = False
95             #if row[3]=='UNI': dict['unique'] = True
96             #else: dict['unique'] = False
97            
98
99 #    print dict
100     return dict
101    
102 def _table_info(cursor, name):
103     cursor.execute('PRAGMA table_info(%s)' % quote_name(name))
104     # cid, name, type, notnull, dflt_value, pk
105     return [{'name': field[1],
106              'type': field[2],
107              'null_ok': not field[3],
108              'pk': field[5]     # undocumented
109              } for field in cursor.fetchall()]
110
111 # Maps SQL types to Django Field types. Some of the SQL types have multiple
112 # entries here because SQLite allows for anything and doesn't normalize the
113 # field type; it uses whatever was given.
114 BASE_DATA_TYPES_REVERSE = {
115     'bool': 'BooleanField',
116     'boolean': 'BooleanField',
117     'smallint': 'SmallIntegerField',
118     'smallinteger': 'SmallIntegerField',
119     'int': 'IntegerField',
120     'integer': 'IntegerField',
121     'text': 'TextField',
122     'char': 'CharField',
123     'date': 'DateField',
124     'datetime': 'DateTimeField',
125     'time': 'TimeField',
126 }
127
128 # This light wrapper "fakes" a dictionary interface, because some SQLite data
129 # types include variables in them -- e.g. "varchar(30)" -- and can't be matched
130 # as a simple dictionary lookup.
131 class FlexibleFieldLookupDict:
132     def __getitem__(self, key):
133         key = key.lower()
134         try:
135             return BASE_DATA_TYPES_REVERSE[key]
136         except KeyError:
137             import re
138             m = re.search(r'^\s*(?:var)?char\s*\(\s*(\d+)\s*\)\s*$', key)
139             if m:
140                 return ('CharField', {'max_length': int(m.group(1))})
141             raise KeyError
142
143 DATA_TYPES_REVERSE = FlexibleFieldLookupDict()
Note: See TracBrowser for help on using the browser.