Skip to content

Commit 68a3df8

Browse files
committed
inspectdb prepare
1 parent 36e5192 commit 68a3df8

File tree

1 file changed

+143
-3
lines changed

1 file changed

+143
-3
lines changed

django_iris/introspection.py

Lines changed: 143 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,48 @@
1+
from collections import namedtuple
2+
13
from django.db.backends.base.introspection import (
24
BaseDatabaseIntrospection, FieldInfo as BaseFieldInfo, TableInfo,
35
)
6+
from django.db.models import Index
7+
from django.utils.datastructures import OrderedSet
48

9+
FieldInfo = namedtuple('FieldInfo', BaseFieldInfo._fields + ('auto_increment', ))
510

611
class DatabaseIntrospection(BaseDatabaseIntrospection):
12+
data_types_reverse = {
13+
'bigint': 'BigIntegerField',
14+
'varchar': 'CharField',
15+
'integer': 'IntegerField',
16+
'bit': 'BooleanField',
17+
'date': 'DateField',
18+
'timestamp': 'DateTimeField',
19+
'numeric': 'IntegerField',
20+
'double': 'FloatField',
21+
'varbinary': 'BinaryField',
22+
'longvarchar': 'TextField',
23+
'longvarbinary': 'BinaryField',
24+
'time': 'TimeField',
25+
'smallint': 'SmallIntegerField',
26+
'tinyint': 'SmallIntegerField',
27+
}
28+
29+
def get_field_type(self, data_type, field_info):
30+
field_type = super().get_field_type(data_type, field_info)
31+
if (field_info.auto_increment and
32+
field_type in {'BigIntegerField', 'IntegerField', 'SmallIntegerField'}):
33+
return 'AutoField'
34+
return field_type
35+
36+
def get_sequences(self, cursor, table_name, table_fields=()):
37+
"""
38+
Return a list of introspected sequences for table_name. Each sequence
39+
is a dict: {'table': <table_name>, 'column': <column_name>}. An optional
40+
'name' key can be added if the backend supports named sequences.
41+
"""
42+
for field_info in self.get_table_description(cursor, table_name):
43+
if 'auto_increment' in field_info and field_info['auto_increment']:
44+
return [{'table': table_name, 'column': field_info.name}]
45+
return []
746

847
def get_table_list(self, cursor):
948
cursor.execute("""
@@ -14,8 +53,109 @@ def get_table_list(self, cursor):
1453
return [TableInfo(row[0], 't') for row in cursor.fetchall()]
1554

1655
def get_table_description(self, cursor, table_name):
17-
print("get_table_description", table_name)
18-
return []
56+
"""
57+
Return a description of the table with the DB-API cursor.description
58+
interface.
59+
"""
60+
61+
cursor.execute("""
62+
SELECT
63+
COLUMN_NAME,
64+
DATA_TYPE,
65+
CHARACTER_MAXIMUM_LENGTH,
66+
NUMERIC_PRECISION,
67+
NUMERIC_SCALE,
68+
IS_NULLABLE,
69+
AUTO_INCREMENT
70+
FROM INFORMATION_SCHEMA.COLUMNS
71+
WHERE TABLE_SCHEMA = %s
72+
AND TABLE_NAME = %s
73+
ORDER BY ORDINAL_POSITION
74+
""",
75+
['SQLUser', table_name]
76+
)
77+
78+
description = [
79+
# name type_code display_size internal_size precision scale null_ok default collation
80+
# auto_increment
81+
FieldInfo(
82+
name,
83+
data_type,
84+
None,
85+
length,
86+
precision,
87+
scale,
88+
isnull == 'YES',
89+
'',
90+
'',
91+
auto_increment == 'YES',
92+
)
93+
for name, data_type, length, precision, scale, isnull, auto_increment in cursor.fetchall()
94+
]
95+
return description
1996

2097
def get_relations(self, cursor, table_name):
21-
return []
98+
"""
99+
Return a dictionary of {field_name: (field_name_other_table, other_table)}
100+
representing all relationships to the given table.
101+
"""
102+
# Dictionary of relations to return
103+
relations = {}
104+
return relations
105+
106+
# def get_primary_key_column(self, cursor, table_name):
107+
# """
108+
# Return the name of the primary key column for the given table.
109+
# """
110+
# return super().get_primary_key_column(cursor, table_name)
111+
112+
def get_constraints(self, cursor, table_name):
113+
"""
114+
Retrieve any constraints or keys (unique, pk, fk, check, index)
115+
across one or more columns.
116+
117+
Return a dict mapping constraint names to their attributes,
118+
where attributes is a dict with keys:
119+
* columns: List of columns this covers
120+
* primary_key: True if primary key, False otherwise
121+
* unique: True if this is a unique constraint, False otherwise
122+
* foreign_key: (table, column) of target, or None
123+
* check: True if check constraint, False otherwise
124+
* index: True if index, False otherwise.
125+
* orders: The order (ASC/DESC) defined for the columns of indexes
126+
* type: The type of the index (btree, hash, etc.)
127+
128+
Some backends may return special constraint names that don't exist
129+
if they don't name constraints of a certain type (e.g. SQLite)
130+
"""
131+
constraints = {}
132+
133+
cursor.execute("""
134+
SELECT
135+
INDEX_NAME,
136+
COLUMN_NAME,
137+
PRIMARY_KEY,
138+
NON_UNIQUE,
139+
ASC_OR_DESC
140+
FROM INFORMATION_SCHEMA. INDEXES
141+
WHERE TABLE_SCHEMA = %s
142+
AND TABLE_NAME = %s
143+
ORDER BY ORDINAL_POSITION
144+
""",
145+
['SQLUser', table_name]
146+
)
147+
for index, column, primary, non_unique, order in cursor.fetchall():
148+
if index not in constraints:
149+
constraints[index] = {
150+
'columns': [],
151+
'primary_key': primary == 1,
152+
'unique': not non_unique,
153+
'check': False,
154+
'foreign_key': None,
155+
'orders': [],
156+
}
157+
constraints[index]['columns'].append(column)
158+
constraints[index]['orders'].append(
159+
'DESC' if order == 'D' else 'ASC')
160+
161+
return constraints

0 commit comments

Comments
 (0)