@@ -53,38 +53,44 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
53
53
}
54
54
55
55
def get_constraints (self , cursor , table_name ):
56
+ table_name = self .connection .ops .quote_name (table_name )
56
57
constraints = {}
57
58
# Foreign keys
58
- cursor .execute (f'SHOW IMPORTED KEYS IN TABLE " { table_name } " ' )
59
+ cursor .execute (f'SHOW IMPORTED KEYS IN TABLE { table_name } ' )
59
60
for row in cursor .fetchall ():
60
61
constraints [row [12 ]] = {
61
- 'columns' : [row [8 ]],
62
+ 'columns' : [self . identifier_converter ( row [8 ]) ],
62
63
'primary_key' : False ,
63
64
'unique' : False ,
64
- 'foreign_key' : (row [3 ], row [4 ]),
65
+ 'foreign_key' : (self . identifier_converter ( row [3 ]), self . identifier_converter ( row [4 ]) ),
65
66
'check' : False ,
66
67
'index' : False ,
67
68
}
68
69
# Primary keys
69
- cursor .execute (f'SHOW PRIMARY KEYS IN TABLE " { table_name } " ' )
70
+ cursor .execute (f'SHOW PRIMARY KEYS IN TABLE { table_name } ' )
70
71
for row in cursor .fetchall ():
71
- constraints [row [6 ]] = {
72
- 'columns' : [row [4 ]],
72
+ # Add quotes around
73
+ constraints ['"' + row [6 ] + '"' ] = {
74
+ 'columns' : [self .identifier_converter (row [4 ])],
73
75
'primary_key' : True ,
74
76
'unique' : False ,
75
77
'foreign_key' : None ,
76
78
'check' : False ,
77
79
'index' : False ,
78
80
}
79
81
# Unique constraints
80
- cursor .execute (f'SHOW UNIQUE KEYS IN TABLE " { table_name } " ' )
82
+ cursor .execute (f'SHOW UNIQUE KEYS IN TABLE { table_name } ' )
81
83
# The columns of multi-column unique indexes are ordered by row[5].
82
84
# Map {constraint_name: [(row[5], column_name), ...] so the columns can
83
85
# be sorted for each constraint.
84
86
unique_column_orders = {}
85
87
for row in cursor .fetchall ():
86
- column_name = row [4 ]
87
- constraint_name = row [6 ]
88
+ column_name = self .identifier_converter (row [4 ])
89
+ # TODO: hack
90
+ constraint_name = (
91
+ '"' + row [6 ] + '"' if row [6 ].startswith ("SYS_CONSTRAINT_" )
92
+ else self .identifier_converter (row [6 ])
93
+ )
88
94
if constraint_name in constraints :
89
95
# If the constraint name is already present, this is a
90
96
# multi-column unique constraint.
@@ -106,16 +112,24 @@ def get_constraints(self, cursor, table_name):
106
112
return constraints
107
113
108
114
def get_primary_key_column (self , cursor , table_name ):
109
- pks = [field .name for field in self .get_table_description (cursor , table_name ) if field .pk ]
115
+ pks = [
116
+ self .identifier_converter (field .name )
117
+ for field in self .get_table_description (cursor , table_name )
118
+ if field .pk
119
+ ]
110
120
return pks [0 ] if pks else None
111
121
112
122
def get_relations (self , cursor , table_name ):
113
123
"""
114
124
Return a dictionary of {field_name: (field_name_other_table, other_table)}
115
125
representing all foreign keys in the given table.
116
126
"""
117
- cursor .execute (f'SHOW IMPORTED KEYS IN TABLE "{ table_name } "' )
118
- return {row [8 ]: (row [4 ], row [3 ]) for row in cursor .fetchall ()}
127
+ table_name = self .connection .ops .quote_name (table_name )
128
+ cursor .execute (f'SHOW IMPORTED KEYS IN TABLE { table_name } ' )
129
+ return {
130
+ self .identifier_converter (row [8 ]): (self .identifier_converter (row [4 ]), self .identifier_converter (row [3 ]))
131
+ for row in cursor .fetchall ()
132
+ }
119
133
120
134
def get_field_type (self , data_type , description ):
121
135
field_type = super ().get_field_type (data_type , description )
@@ -145,22 +159,28 @@ def get_table_description(self, cursor, table_name):
145
159
table_info = cursor .fetchall ()
146
160
return [
147
161
FieldInfo (
148
- # name, type_code, display_size, internal_size,
149
- name , get_data_type (data_type ), None , get_field_size ( data_type ) ,
150
- # precision, scale, null_ok, default ,
151
- * get_precision_and_scale (data_type ), null == 'Y' , default ,
152
- # collation, pk,
153
- get_collation (data_type ), pk == 'Y' ,
162
+ # name, type_code, display_size,
163
+ self . identifier_converter ( name ) , get_data_type (data_type ), None ,
164
+ # internal_size, precision, scale ,
165
+ get_field_size (data_type ), * get_precision_and_scale ( data_type ) ,
166
+ # null_ok, default, collation, pk,
167
+ null == 'Y' , default , get_collation (data_type ), pk == 'Y' ,
154
168
)
155
169
for (
156
170
name , data_type , kind , null , default , pk , unique_key , check ,
157
171
expression , comment , policy_name ,
158
172
) in table_info
159
173
]
160
174
175
+ def identifier_converter (self , name ):
176
+ """Identifier comparison is case insensitive on Snowflake."""
177
+ # if name != name.upper():
178
+ # return f'"{name}"'
179
+ return name .lower ()
180
+
161
181
def get_table_list (self , cursor ):
162
182
cursor .execute ('SHOW TERSE TABLES' )
163
- tables = [TableInfo (row [1 ], 't' ) for row in cursor .fetchall ()]
183
+ tables = [TableInfo (self . identifier_converter ( row [1 ]) , 't' ) for row in cursor .fetchall ()]
164
184
cursor .execute ('SHOW TERSE VIEWS' )
165
- views = [TableInfo (row [1 ], 'v' ) for row in cursor .fetchall ()]
185
+ views = [TableInfo (self . identifier_converter ( row [1 ]) , 'v' ) for row in cursor .fetchall ()]
166
186
return tables + views
0 commit comments