diff --git a/django/db/backends/base/introspection.py b/django/db/backends/base/introspection.py
index cefdecea0a..52da90b7e9 100644
a
|
b
|
class BaseDatabaseIntrospection:
|
40 | 40 | """ |
41 | 41 | return self.table_name_converter(name) |
42 | 42 | |
| 43 | def identifier_converter(self, name): |
| 44 | """ |
| 45 | Apply a conversion to the identifier for the purposes of comparison. |
| 46 | |
| 47 | Use table_name_converter() by default. |
| 48 | """ |
| 49 | return self.table_name_converter(name) |
| 50 | |
43 | 51 | def table_names(self, cursor=None, include_views=False): |
44 | 52 | """ |
45 | 53 | Return a list of names of all tables that exist in the database. |
diff --git a/django/db/backends/oracle/introspection.py b/django/db/backends/oracle/introspection.py
index e5597fd56c..a2da8325fe 100644
a
|
b
|
class DatabaseIntrospection(BaseDatabaseIntrospection):
|
186 | 186 | GROUP BY user_constraints.constraint_name, user_constraints.constraint_type |
187 | 187 | """, [table_name]) |
188 | 188 | for constraint, columns, pk, unique, check in cursor.fetchall(): |
| 189 | constraint = self.identifier_converter(constraint) |
189 | 190 | constraints[constraint] = { |
190 | 191 | 'columns': columns.split(','), |
191 | 192 | 'primary_key': pk, |
… |
… |
class DatabaseIntrospection(BaseDatabaseIntrospection):
|
213 | 214 | GROUP BY cons.constraint_name, rcols.table_name, rcols.column_name |
214 | 215 | """, [table_name]) |
215 | 216 | for constraint, columns, other_table, other_column in cursor.fetchall(): |
| 217 | constraint = self.identifier_converter(constraint) |
216 | 218 | constraints[constraint] = { |
217 | 219 | 'primary_key': False, |
218 | 220 | 'unique': False, |
… |
… |
class DatabaseIntrospection(BaseDatabaseIntrospection):
|
240 | 242 | GROUP BY ind.index_name, ind.index_type |
241 | 243 | """, [table_name]) |
242 | 244 | for constraint, type_, columns, orders in cursor.fetchall(): |
| 245 | constraint = self.identifier_converter(constraint) |
243 | 246 | constraints[constraint] = { |
244 | 247 | 'primary_key': False, |
245 | 248 | 'unique': False, |
diff --git a/docs/releases/2.2.txt b/docs/releases/2.2.txt
index 4dd3c72e20..8d832e05fb 100644
a
|
b
|
Database backend API
|
293 | 293 | * Third party database backends must implement support for partial indexes or |
294 | 294 | set ``DatabaseFeatures.supports_partial_indexes`` to ``False``. |
295 | 295 | |
| 296 | * ``DatabaseIntrospection.get_constraints()`` must return lower name constraint |
| 297 | names, even when ``DatabaseFeatures.uppercases_column_names`` is ``True``. |
| 298 | |
296 | 299 | Admin actions are no longer collected from base ``ModelAdmin`` classes |
297 | 300 | ---------------------------------------------------------------------- |
298 | 301 | |
diff --git a/tests/schema/tests.py b/tests/schema/tests.py
index 7f170c863e..d9dda84fec 100644
a
|
b
|
class SchemaTests(TransactionTestCase):
|
1868 | 1868 | table_name=AuthorWithIndexedName._meta.db_table, |
1869 | 1869 | column_names=('name',), |
1870 | 1870 | ) |
1871 | | if connection.features.uppercases_column_names: |
1872 | | author_index_name = author_index_name.upper() |
1873 | | db_index_name = db_index_name.upper() |
1874 | 1871 | try: |
1875 | 1872 | AuthorWithIndexedName._meta.indexes = [index] |
1876 | 1873 | with connection.schema_editor() as editor: |
… |
… |
class SchemaTests(TransactionTestCase):
|
1908 | 1905 | with connection.schema_editor() as editor: |
1909 | 1906 | editor.add_index(Author, index) |
1910 | 1907 | if connection.features.supports_index_column_ordering: |
1911 | | if connection.features.uppercases_column_names: |
1912 | | index_name = index_name.upper() |
1913 | 1908 | self.assertIndexOrder(Author._meta.db_table, index_name, ['ASC', 'DESC']) |
1914 | 1909 | # Drop the index |
1915 | 1910 | with connection.schema_editor() as editor: |
… |
… |
class SchemaTests(TransactionTestCase):
|
2127 | 2122 | editor.create_model(model) |
2128 | 2123 | editor.add_field(model, field) |
2129 | 2124 | |
2130 | | constraint_name = "CamelCaseIndex" |
| 2125 | constraint_name = 'CamelCaseIndex' |
| 2126 | expected_constraint_name = constraint_name.lower() |
2131 | 2127 | editor.execute( |
2132 | 2128 | editor.sql_create_index % { |
2133 | 2129 | "table": editor.quote_name(table), |
… |
… |
class SchemaTests(TransactionTestCase):
|
2138 | 2134 | "condition": "", |
2139 | 2135 | } |
2140 | 2136 | ) |
2141 | | if connection.features.uppercases_column_names: |
2142 | | constraint_name = constraint_name.upper() |
2143 | | self.assertIn(constraint_name, self.get_constraints(model._meta.db_table)) |
| 2137 | self.assertIn(expected_constraint_name, self.get_constraints(model._meta.db_table)) |
2144 | 2138 | editor.alter_field(model, get_field(db_index=True), field, strict=True) |
2145 | | self.assertNotIn(constraint_name, self.get_constraints(model._meta.db_table)) |
| 2139 | self.assertNotIn(expected_constraint_name, self.get_constraints(model._meta.db_table)) |
2146 | 2140 | |
2147 | 2141 | constraint_name = "CamelCaseUniqConstraint" |
| 2142 | expected_constraint_name = constraint_name.lower() |
2148 | 2143 | editor.execute( |
2149 | 2144 | editor.sql_create_unique % { |
2150 | 2145 | "table": editor.quote_name(table), |
… |
… |
class SchemaTests(TransactionTestCase):
|
2152 | 2147 | "columns": editor.quote_name(field.column), |
2153 | 2148 | } |
2154 | 2149 | ) |
2155 | | if connection.features.uppercases_column_names: |
2156 | | constraint_name = constraint_name.upper() |
2157 | | self.assertIn(constraint_name, self.get_constraints(model._meta.db_table)) |
| 2150 | self.assertIn(expected_constraint_name, self.get_constraints(model._meta.db_table)) |
2158 | 2151 | editor.alter_field(model, get_field(unique=True), field, strict=True) |
2159 | | self.assertNotIn(constraint_name, self.get_constraints(model._meta.db_table)) |
| 2152 | self.assertNotIn(expected_constraint_name, self.get_constraints(model._meta.db_table)) |
2160 | 2153 | |
2161 | 2154 | if editor.sql_create_fk: |
2162 | 2155 | constraint_name = "CamelCaseFKConstraint" |
| 2156 | expected_constraint_name = constraint_name.lower() |
2163 | 2157 | editor.execute( |
2164 | 2158 | editor.sql_create_fk % { |
2165 | 2159 | "table": editor.quote_name(table), |
… |
… |
class SchemaTests(TransactionTestCase):
|
2170 | 2164 | "deferrable": connection.ops.deferrable_sql(), |
2171 | 2165 | } |
2172 | 2166 | ) |
2173 | | if connection.features.uppercases_column_names: |
2174 | | constraint_name = constraint_name.upper() |
2175 | | self.assertIn(constraint_name, self.get_constraints(model._meta.db_table)) |
| 2167 | self.assertIn(expected_constraint_name, self.get_constraints(model._meta.db_table)) |
2176 | 2168 | editor.alter_field(model, get_field(Author, CASCADE, field_class=ForeignKey), field, strict=True) |
2177 | | self.assertNotIn(constraint_name, self.get_constraints(model._meta.db_table)) |
| 2169 | self.assertNotIn(expected_constraint_name, self.get_constraints(model._meta.db_table)) |
2178 | 2170 | |
2179 | 2171 | def test_add_field_use_effective_default(self): |
2180 | 2172 | """ |
… |
… |
class SchemaTests(TransactionTestCase):
|
2491 | 2483 | new_field.set_attributes_from_name('weight') |
2492 | 2484 | with connection.schema_editor() as editor: |
2493 | 2485 | editor.alter_field(Author, old_field, new_field, strict=True) |
2494 | | |
2495 | | expected = 'schema_author_weight_587740f9' |
2496 | | if connection.features.uppercases_column_names: |
2497 | | expected = expected.upper() |
2498 | | self.assertEqual(self.get_constraints_for_column(Author, 'weight'), [expected]) |
2499 | | |
| 2486 | self.assertEqual(self.get_constraints_for_column(Author, 'weight'), ['schema_author_weight_587740f9']) |
2500 | 2487 | # Remove db_index=True to drop index. |
2501 | 2488 | with connection.schema_editor() as editor: |
2502 | 2489 | editor.alter_field(Author, new_field, old_field, strict=True) |