6
6
from django .db .models import Index
7
7
from django .utils .datastructures import OrderedSet
8
8
9
- FieldInfo = namedtuple ('FieldInfo' , BaseFieldInfo ._fields + ('auto_increment' , ))
9
+ FieldInfo = namedtuple (
10
+ 'FieldInfo' , BaseFieldInfo ._fields + ('auto_increment' , ))
11
+
10
12
11
13
class DatabaseIntrospection (BaseDatabaseIntrospection ):
12
14
data_types_reverse = {
@@ -100,8 +102,18 @@ def get_relations(self, cursor, table_name):
100
102
representing all relationships to the given table.
101
103
"""
102
104
# Dictionary of relations to return
103
- relations = {}
104
- return relations
105
+ cursor .execute ("""
106
+ SELECT column_name, referenced_column_name, referenced_table_name
107
+ FROM information_schema.key_column_usage
108
+ WHERE table_schema = %s
109
+ AND table_name = %s
110
+ AND referenced_table_name IS NOT NULL
111
+ AND referenced_column_name IS NOT NULL
112
+ """ , ['SQLUser' , table_name ])
113
+ return {
114
+ field_name : (other_field , other_table )
115
+ for field_name , other_field , other_table in cursor .fetchall ()
116
+ }
105
117
106
118
# def get_primary_key_column(self, cursor, table_name):
107
119
# """
@@ -129,8 +141,73 @@ def get_constraints(self, cursor, table_name):
129
141
if they don't name constraints of a certain type (e.g. SQLite)
130
142
"""
131
143
constraints = {}
144
+ # Get the actual constraint names and columns
145
+ name_query = """
146
+ SELECT kc.constraint_name, kc.column_name,
147
+ kc.referenced_table_name, kc.referenced_column_name,
148
+ c.constraint_type
149
+ FROM
150
+ information_schema.key_column_usage AS kc,
151
+ information_schema.table_constraints AS c
152
+ WHERE
153
+ kc.table_schema = %s AND
154
+ c.table_schema = kc.table_schema AND
155
+ c.constraint_name = kc.constraint_name AND
156
+ c.constraint_type != 'CHECK' AND
157
+ kc.table_name = %s
158
+ ORDER BY kc.ordinal_position
159
+ """
160
+ cursor .execute (name_query , ['SQLUser' , table_name ])
161
+ for constraint , column , ref_table , ref_column , kind in cursor .fetchall ():
162
+ if constraint not in constraints :
163
+ constraints [constraint ] = {
164
+ 'columns' : OrderedSet (),
165
+ 'primary_key' : kind == 'PRIMARY KEY' ,
166
+ 'unique' : kind in {'PRIMARY KEY' , 'UNIQUE' },
167
+ 'index' : False ,
168
+ 'check' : False ,
169
+ 'foreign_key' : (ref_table , ref_column ) if ref_column else None ,
170
+ }
171
+ if self .connection .features .supports_index_column_ordering :
172
+ constraints [constraint ]['orders' ] = []
173
+ constraints [constraint ]['columns' ].add (column )
174
+ # Add check constraints.
175
+ if self .connection .features .can_introspect_check_constraints :
176
+ unnamed_constraints_index = 0
177
+ columns = {info .name for info in self .get_table_description (
178
+ cursor , table_name )}
179
+ type_query = """
180
+ SELECT cc.constraint_name, cc.check_clause
181
+ FROM
182
+ information_schema.check_constraints AS cc,
183
+ information_schema.table_constraints AS tc
184
+ WHERE
185
+ cc.constraint_schema = %s AND
186
+ tc.table_schema = cc.constraint_schema AND
187
+ cc.constraint_name = tc.constraint_name AND
188
+ tc.constraint_type = 'CHECK' AND
189
+ tc.table_name = %s
190
+ """
191
+ cursor .execute (type_query , ['SQLUser' , table_name ])
192
+ for constraint , check_clause in cursor .fetchall ():
193
+ constraint_columns = self ._parse_constraint_columns (
194
+ check_clause , columns )
195
+ # Ensure uniqueness of unnamed constraints. Unnamed unique
196
+ # and check columns constraints have the same name as
197
+ # a column.
198
+ if set (constraint_columns ) == {constraint }:
199
+ unnamed_constraints_index += 1
200
+ constraint = '__unnamed_constraint_%s__' % unnamed_constraints_index
201
+ constraints [constraint ] = {
202
+ 'columns' : constraint_columns ,
203
+ 'primary_key' : False ,
204
+ 'unique' : False ,
205
+ 'index' : False ,
206
+ 'check' : True ,
207
+ 'foreign_key' : None ,
208
+ }
132
209
133
- cursor . execute ( """
210
+ index_query = """
134
211
SELECT
135
212
INDEX_NAME,
136
213
COLUMN_NAME,
@@ -141,21 +218,23 @@ def get_constraints(self, cursor, table_name):
141
218
WHERE TABLE_SCHEMA = %s
142
219
AND TABLE_NAME = %s
143
220
ORDER BY ORDINAL_POSITION
144
- """ ,
145
- ['SQLUser' , table_name ]
146
- )
221
+ """
222
+ cursor .execute (index_query , ['SQLUser' , table_name ])
147
223
for index , column , primary , non_unique , order in cursor .fetchall ():
148
224
if index not in constraints :
149
225
constraints [index ] = {
150
- 'columns' : [] ,
226
+ 'columns' : OrderedSet () ,
151
227
'primary_key' : primary == 1 ,
152
228
'unique' : not non_unique ,
153
229
'check' : False ,
154
230
'foreign_key' : None ,
155
231
'orders' : [],
156
232
}
157
- constraints [index ]['columns' ].append (column )
233
+ constraints [index ]['columns' ].add (column )
158
234
constraints [index ]['orders' ].append (
159
235
'DESC' if order == 'D' else 'ASC' )
160
236
237
+ # Convert the sorted sets to lists
238
+ for constraint in constraints .values ():
239
+ constraint ['columns' ] = list (constraint ['columns' ])
161
240
return constraints
0 commit comments