Unverified Kaydet (Commit) d5f4ce98 authored tarafından Mariusz Felisiak's avatar Mariusz Felisiak Kaydeden (comit) GitHub

Fixed #29949 -- Refactored db introspection identifier converters.

Removed DatabaseIntrospection.table_name_converter()/column_name_converter()
and use instead DatabaseIntrospection.identifier_converter().

Removed DatabaseFeatures.uppercases_column_names.

Thanks Tim Graham for the initial patch and review and Simon Charette
for the review.
üst 2e477619
...@@ -308,7 +308,7 @@ class Command(BaseCommand): ...@@ -308,7 +308,7 @@ class Command(BaseCommand):
def model_installed(model): def model_installed(model):
opts = model._meta opts = model._meta
converter = connection.introspection.table_name_converter converter = connection.introspection.identifier_converter
return not ( return not (
(converter(opts.db_table) in tables) or (converter(opts.db_table) in tables) or
(opts.auto_created and converter(opts.auto_created._meta.db_table) in tables) (opts.auto_created and converter(opts.auto_created._meta.db_table) in tables)
......
...@@ -200,8 +200,6 @@ class BaseDatabaseFeatures: ...@@ -200,8 +200,6 @@ class BaseDatabaseFeatures:
# If NULL is implied on columns without needing to be explicitly specified # If NULL is implied on columns without needing to be explicitly specified
implied_column_null = False implied_column_null = False
uppercases_column_names = False
# Does the backend support "select for update" queries with limit (and offset)? # Does the backend support "select for update" queries with limit (and offset)?
supports_select_for_update_with_limit = True supports_select_for_update_with_limit = True
......
...@@ -24,22 +24,14 @@ class BaseDatabaseIntrospection: ...@@ -24,22 +24,14 @@ class BaseDatabaseIntrospection:
""" """
return self.data_types_reverse[data_type] return self.data_types_reverse[data_type]
def table_name_converter(self, name): def identifier_converter(self, name):
""" """
Apply a conversion to the name for the purposes of comparison. Apply a conversion to the identifier for the purposes of comparison.
The default table name converter is for case sensitive comparison. The default identifier converter is for case sensitive comparison.
""" """
return name return name
def column_name_converter(self, name):
"""
Apply a conversion to the column name for the purposes of comparison.
Use table_name_converter() by default.
"""
return self.table_name_converter(name)
def table_names(self, cursor=None, include_views=False): def table_names(self, cursor=None, include_views=False):
""" """
Return a list of names of all tables that exist in the database. Return a list of names of all tables that exist in the database.
...@@ -83,11 +75,11 @@ class BaseDatabaseIntrospection: ...@@ -83,11 +75,11 @@ class BaseDatabaseIntrospection:
) )
tables = list(tables) tables = list(tables)
if only_existing: if only_existing:
existing_tables = self.table_names(include_views=include_views) existing_tables = set(self.table_names(include_views=include_views))
tables = [ tables = [
t t
for t in tables for t in tables
if self.table_name_converter(t) in existing_tables if self.identifier_converter(t) in existing_tables
] ]
return tables return tables
...@@ -101,10 +93,10 @@ class BaseDatabaseIntrospection: ...@@ -101,10 +93,10 @@ class BaseDatabaseIntrospection:
all_models = [] all_models = []
for app_config in apps.get_app_configs(): for app_config in apps.get_app_configs():
all_models.extend(router.get_migratable_models(app_config, self.connection.alias)) all_models.extend(router.get_migratable_models(app_config, self.connection.alias))
tables = list(map(self.table_name_converter, tables)) tables = set(map(self.identifier_converter, tables))
return { return {
m for m in all_models m for m in all_models
if self.table_name_converter(m._meta.db_table) in tables if self.identifier_converter(m._meta.db_table) in tables
} }
def sequence_list(self): def sequence_list(self):
......
...@@ -1048,7 +1048,7 @@ class BaseDatabaseSchemaEditor: ...@@ -1048,7 +1048,7 @@ class BaseDatabaseSchemaEditor:
"""Return all constraint names matching the columns and conditions.""" """Return all constraint names matching the columns and conditions."""
if column_names is not None: if column_names is not None:
column_names = [ column_names = [
self.connection.introspection.column_name_converter(name) self.connection.introspection.identifier_converter(name)
for name in column_names for name in column_names
] ]
with self.connection.cursor() as cursor: with self.connection.cursor() as cursor:
......
...@@ -28,7 +28,6 @@ class DatabaseFeatures(BaseDatabaseFeatures): ...@@ -28,7 +28,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
requires_literal_defaults = True requires_literal_defaults = True
closed_cursor_error_class = InterfaceError closed_cursor_error_class = InterfaceError
bare_select_suffix = " FROM DUAL" bare_select_suffix = " FROM DUAL"
uppercases_column_names = True
# select for update with limit can be achieved on Oracle, but not with the current backend. # select for update with limit can be achieved on Oracle, but not with the current backend.
supports_select_for_update_with_limit = False supports_select_for_update_with_limit = False
supports_temporal_subtraction = True supports_temporal_subtraction = True
......
...@@ -50,7 +50,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): ...@@ -50,7 +50,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
"""Return a list of table and view names in the current database.""" """Return a list of table and view names in the current database."""
cursor.execute("SELECT TABLE_NAME, 't' FROM USER_TABLES UNION ALL " cursor.execute("SELECT TABLE_NAME, 't' FROM USER_TABLES UNION ALL "
"SELECT VIEW_NAME, 'v' FROM USER_VIEWS") "SELECT VIEW_NAME, 'v' FROM USER_VIEWS")
return [TableInfo(row[0].lower(), row[1]) for row in cursor.fetchall()] return [TableInfo(self.identifier_converter(row[0]), row[1]) for row in cursor.fetchall()]
def get_table_description(self, cursor, table_name): def get_table_description(self, cursor, table_name):
""" """
...@@ -86,13 +86,13 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): ...@@ -86,13 +86,13 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
internal_size, default, is_autofield = field_map[name] internal_size, default, is_autofield = field_map[name]
name = name % {} # cx_Oracle, for some reason, doubles percent signs. name = name % {} # cx_Oracle, for some reason, doubles percent signs.
description.append(FieldInfo( description.append(FieldInfo(
name.lower(), *desc[1:3], internal_size, desc[4] or 0, self.identifier_converter(name), *desc[1:3], internal_size, desc[4] or 0,
desc[5] or 0, *desc[6:], default, is_autofield, desc[5] or 0, *desc[6:], default, is_autofield,
)) ))
return description return description
def table_name_converter(self, name): def identifier_converter(self, name):
"""Table name comparison is case insensitive under Oracle.""" """Identifier comparison is case insensitive under Oracle."""
return name.lower() return name.lower()
def get_sequences(self, cursor, table_name, table_fields=()): def get_sequences(self, cursor, table_name, table_fields=()):
...@@ -114,7 +114,11 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): ...@@ -114,7 +114,11 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
# Oracle allows only one identity column per table. # Oracle allows only one identity column per table.
row = cursor.fetchone() row = cursor.fetchone()
if row: if row:
return [{'name': row[0].lower(), 'table': table_name, 'column': row[1].lower()}] return [{
'name': self.identifier_converter(row[0]),
'table': self.identifier_converter(table_name),
'column': self.identifier_converter(row[1]),
}]
# To keep backward compatibility for AutoFields that aren't Oracle # To keep backward compatibility for AutoFields that aren't Oracle
# identity columns. # identity columns.
for f in table_fields: for f in table_fields:
...@@ -136,10 +140,12 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): ...@@ -136,10 +140,12 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
user_constraints.r_constraint_name = cb.constraint_name AND user_constraints.r_constraint_name = cb.constraint_name AND
ca.position = cb.position""", [table_name]) ca.position = cb.position""", [table_name])
relations = {} return {
for row in cursor.fetchall(): self.identifier_converter(field_name): (
relations[row[0].lower()] = (row[2].lower(), row[1].lower()) self.identifier_converter(rel_field_name),
return relations self.identifier_converter(rel_table_name),
) for field_name, rel_table_name, rel_field_name in cursor.fetchall()
}
def get_key_columns(self, cursor, table_name): def get_key_columns(self, cursor, table_name):
cursor.execute(""" cursor.execute("""
...@@ -150,8 +156,10 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): ...@@ -150,8 +156,10 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
JOIN user_cons_columns rcol JOIN user_cons_columns rcol
ON rcol.constraint_name = c.r_constraint_name ON rcol.constraint_name = c.r_constraint_name
WHERE c.table_name = %s AND c.constraint_type = 'R'""", [table_name.upper()]) WHERE c.table_name = %s AND c.constraint_type = 'R'""", [table_name.upper()])
return [tuple(cell.lower() for cell in row) return [
for row in cursor.fetchall()] tuple(self.identifier_converter(cell) for cell in row)
for row in cursor.fetchall()
]
def get_constraints(self, cursor, table_name): def get_constraints(self, cursor, table_name):
""" """
...@@ -186,6 +194,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): ...@@ -186,6 +194,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
GROUP BY user_constraints.constraint_name, user_constraints.constraint_type GROUP BY user_constraints.constraint_name, user_constraints.constraint_type
""", [table_name]) """, [table_name])
for constraint, columns, pk, unique, check in cursor.fetchall(): for constraint, columns, pk, unique, check in cursor.fetchall():
constraint = self.identifier_converter(constraint)
constraints[constraint] = { constraints[constraint] = {
'columns': columns.split(','), 'columns': columns.split(','),
'primary_key': pk, 'primary_key': pk,
...@@ -213,6 +222,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): ...@@ -213,6 +222,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
GROUP BY cons.constraint_name, rcols.table_name, rcols.column_name GROUP BY cons.constraint_name, rcols.table_name, rcols.column_name
""", [table_name]) """, [table_name])
for constraint, columns, other_table, other_column in cursor.fetchall(): for constraint, columns, other_table, other_column in cursor.fetchall():
constraint = self.identifier_converter(constraint)
constraints[constraint] = { constraints[constraint] = {
'primary_key': False, 'primary_key': False,
'unique': False, 'unique': False,
...@@ -240,6 +250,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): ...@@ -240,6 +250,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
GROUP BY ind.index_name, ind.index_type GROUP BY ind.index_name, ind.index_type
""", [table_name]) """, [table_name])
for constraint, type_, columns, orders in cursor.fetchall(): for constraint, type_, columns, orders in cursor.fetchall():
constraint = self.identifier_converter(constraint)
constraints[constraint] = { constraints[constraint] = {
'primary_key': False, 'primary_key': False,
'unique': False, 'unique': False,
......
...@@ -1347,7 +1347,7 @@ class RawQuerySet: ...@@ -1347,7 +1347,7 @@ class RawQuerySet:
def resolve_model_init_order(self): def resolve_model_init_order(self):
"""Resolve the init field names and value positions.""" """Resolve the init field names and value positions."""
converter = connections[self.db].introspection.column_name_converter converter = connections[self.db].introspection.identifier_converter
model_init_fields = [f for f in self.model._meta.fields if converter(f.column) in self.columns] model_init_fields = [f for f in self.model._meta.fields if converter(f.column) in self.columns]
annotation_fields = [(column, pos) for pos, column in enumerate(self.columns) annotation_fields = [(column, pos) for pos, column in enumerate(self.columns)
if column not in self.model_fields] if column not in self.model_fields]
...@@ -1469,7 +1469,7 @@ class RawQuerySet: ...@@ -1469,7 +1469,7 @@ class RawQuerySet:
@cached_property @cached_property
def model_fields(self): def model_fields(self):
"""A dict mapping column names to model field names.""" """A dict mapping column names to model field names."""
converter = connections[self.db].introspection.table_name_converter converter = connections[self.db].introspection.identifier_converter
model_fields = {} model_fields = {}
for field in self.model._meta.fields: for field in self.model._meta.fields:
name, column = field.get_attname_column() name, column = field.get_attname_column()
......
...@@ -92,7 +92,7 @@ class RawQuery: ...@@ -92,7 +92,7 @@ class RawQuery:
def get_columns(self): def get_columns(self):
if self.cursor is None: if self.cursor is None:
self._execute_query() self._execute_query()
converter = connections[self.using].introspection.column_name_converter converter = connections[self.using].introspection.identifier_converter
return [converter(column_meta[0]) return [converter(column_meta[0])
for column_meta in self.cursor.description] for column_meta in self.cursor.description]
......
...@@ -312,6 +312,13 @@ backends. ...@@ -312,6 +312,13 @@ backends.
* ``sql_create_fk`` is replaced with ``sql_foreign_key_constraint``, * ``sql_create_fk`` is replaced with ``sql_foreign_key_constraint``,
``sql_constraint``, and ``sql_create_constraint``. ``sql_constraint``, and ``sql_create_constraint``.
* ``DatabaseIntrospection.table_name_converter()`` and
``column_name_converter()`` are removed. Third party database backends may
need to instead implement ``DatabaseIntrospection.identifier_converter()``.
In that case, the constraint names that
``DatabaseIntrospection.get_constraints()`` returns must be normalized by
``identifier_converter()``.
Admin actions are no longer collected from base ``ModelAdmin`` classes Admin actions are no longer collected from base ``ModelAdmin`` classes
---------------------------------------------------------------------- ----------------------------------------------------------------------
......
...@@ -80,7 +80,7 @@ class ParameterHandlingTest(TestCase): ...@@ -80,7 +80,7 @@ class ParameterHandlingTest(TestCase):
"An executemany call with too many/not enough parameters will raise an exception (Refs #12612)" "An executemany call with too many/not enough parameters will raise an exception (Refs #12612)"
with connection.cursor() as cursor: with connection.cursor() as cursor:
query = ('INSERT INTO %s (%s, %s) VALUES (%%s, %%s)' % ( query = ('INSERT INTO %s (%s, %s) VALUES (%%s, %%s)' % (
connection.introspection.table_name_converter('backends_square'), connection.introspection.identifier_converter('backends_square'),
connection.ops.quote_name('root'), connection.ops.quote_name('root'),
connection.ops.quote_name('square') connection.ops.quote_name('square')
)) ))
...@@ -217,7 +217,7 @@ class BackendTestCase(TransactionTestCase): ...@@ -217,7 +217,7 @@ class BackendTestCase(TransactionTestCase):
def create_squares(self, args, paramstyle, multiple): def create_squares(self, args, paramstyle, multiple):
opts = Square._meta opts = Square._meta
tbl = connection.introspection.table_name_converter(opts.db_table) tbl = connection.introspection.identifier_converter(opts.db_table)
f1 = connection.ops.quote_name(opts.get_field('root').column) f1 = connection.ops.quote_name(opts.get_field('root').column)
f2 = connection.ops.quote_name(opts.get_field('square').column) f2 = connection.ops.quote_name(opts.get_field('square').column)
if paramstyle == 'format': if paramstyle == 'format':
...@@ -303,7 +303,7 @@ class BackendTestCase(TransactionTestCase): ...@@ -303,7 +303,7 @@ class BackendTestCase(TransactionTestCase):
'SELECT %s, %s FROM %s ORDER BY %s' % ( 'SELECT %s, %s FROM %s ORDER BY %s' % (
qn(f3.column), qn(f3.column),
qn(f4.column), qn(f4.column),
connection.introspection.table_name_converter(opts2.db_table), connection.introspection.identifier_converter(opts2.db_table),
qn(f3.column), qn(f3.column),
) )
) )
......
...@@ -48,8 +48,6 @@ class CheckConstraintTests(TestCase): ...@@ -48,8 +48,6 @@ class CheckConstraintTests(TestCase):
def test_name(self): def test_name(self):
constraints = get_constraints(Product._meta.db_table) constraints = get_constraints(Product._meta.db_table)
expected_name = 'price_gt_discounted_price' expected_name = 'price_gt_discounted_price'
if connection.features.uppercases_column_names:
expected_name = expected_name.upper()
self.assertIn(expected_name, constraints) self.assertIn(expected_name, constraints)
...@@ -87,6 +85,4 @@ class UniqueConstraintTests(TestCase): ...@@ -87,6 +85,4 @@ class UniqueConstraintTests(TestCase):
def test_name(self): def test_name(self):
constraints = get_constraints(Product._meta.db_table) constraints = get_constraints(Product._meta.db_table)
expected_name = 'unique_name' expected_name = 'unique_name'
if connection.features.uppercases_column_names:
expected_name = expected_name.upper()
self.assertIn(expected_name, constraints) self.assertIn(expected_name, constraints)
...@@ -63,12 +63,9 @@ class OperationTestCase(TransactionTestCase): ...@@ -63,12 +63,9 @@ class OperationTestCase(TransactionTestCase):
self.current_state = self.apply_operations('gis', ProjectState(), operations) self.current_state = self.apply_operations('gis', ProjectState(), operations)
def assertGeometryColumnsCount(self, expected_count): def assertGeometryColumnsCount(self, expected_count):
table_name = 'gis_neighborhood'
if connection.features.uppercases_column_names:
table_name = table_name.upper()
self.assertEqual( self.assertEqual(
GeometryColumns.objects.filter(**{ GeometryColumns.objects.filter(**{
GeometryColumns.table_name_col(): table_name, '%s__iexact' % GeometryColumns.table_name_col(): 'gis_neighborhood',
}).count(), }).count(),
expected_count expected_count
) )
......
...@@ -184,7 +184,7 @@ class InspectDBTestCase(TestCase): ...@@ -184,7 +184,7 @@ class InspectDBTestCase(TestCase):
out = StringIO() out = StringIO()
call_command('inspectdb', table_name_filter=special_table_only, stdout=out) call_command('inspectdb', table_name_filter=special_table_only, stdout=out)
output = out.getvalue() output = out.getvalue()
base_name = 'field' if connection.features.uppercases_column_names else 'Field' base_name = connection.introspection.identifier_converter('Field')
self.assertIn("field = models.IntegerField()", output) self.assertIn("field = models.IntegerField()", output)
self.assertIn("field_field = models.IntegerField(db_column='%s_')" % base_name, output) self.assertIn("field_field = models.IntegerField(db_column='%s_')" % base_name, output)
self.assertIn("field_field_0 = models.IntegerField(db_column='%s__')" % base_name, output) self.assertIn("field_field_0 = models.IntegerField(db_column='%s__')" % base_name, output)
......
...@@ -85,7 +85,7 @@ class SchemaTests(TransactionTestCase): ...@@ -85,7 +85,7 @@ class SchemaTests(TransactionTestCase):
def delete_tables(self): def delete_tables(self):
"Deletes all model tables for our models for a clean test environment" "Deletes all model tables for our models for a clean test environment"
converter = connection.introspection.table_name_converter converter = connection.introspection.identifier_converter
with connection.schema_editor() as editor: with connection.schema_editor() as editor:
connection.disable_constraint_checking() connection.disable_constraint_checking()
table_names = connection.introspection.table_names() table_names = connection.introspection.table_names()
...@@ -1868,9 +1868,6 @@ class SchemaTests(TransactionTestCase): ...@@ -1868,9 +1868,6 @@ class SchemaTests(TransactionTestCase):
table_name=AuthorWithIndexedName._meta.db_table, table_name=AuthorWithIndexedName._meta.db_table,
column_names=('name',), column_names=('name',),
) )
if connection.features.uppercases_column_names:
author_index_name = author_index_name.upper()
db_index_name = db_index_name.upper()
try: try:
AuthorWithIndexedName._meta.indexes = [index] AuthorWithIndexedName._meta.indexes = [index]
with connection.schema_editor() as editor: with connection.schema_editor() as editor:
...@@ -1908,8 +1905,6 @@ class SchemaTests(TransactionTestCase): ...@@ -1908,8 +1905,6 @@ class SchemaTests(TransactionTestCase):
with connection.schema_editor() as editor: with connection.schema_editor() as editor:
editor.add_index(Author, index) editor.add_index(Author, index)
if connection.features.supports_index_column_ordering: if connection.features.supports_index_column_ordering:
if connection.features.uppercases_column_names:
index_name = index_name.upper()
self.assertIndexOrder(Author._meta.db_table, index_name, ['ASC', 'DESC']) self.assertIndexOrder(Author._meta.db_table, index_name, ['ASC', 'DESC'])
# Drop the index # Drop the index
with connection.schema_editor() as editor: with connection.schema_editor() as editor:
...@@ -2122,12 +2117,14 @@ class SchemaTests(TransactionTestCase): ...@@ -2122,12 +2117,14 @@ class SchemaTests(TransactionTestCase):
field = get_field() field = get_field()
table = model._meta.db_table table = model._meta.db_table
column = field.column column = field.column
identifier_converter = connection.introspection.identifier_converter
with connection.schema_editor() as editor: with connection.schema_editor() as editor:
editor.create_model(model) editor.create_model(model)
editor.add_field(model, field) editor.add_field(model, field)
constraint_name = "CamelCaseIndex" constraint_name = 'CamelCaseIndex'
expected_constraint_name = identifier_converter(constraint_name)
editor.execute( editor.execute(
editor.sql_create_index % { editor.sql_create_index % {
"table": editor.quote_name(table), "table": editor.quote_name(table),
...@@ -2138,22 +2135,20 @@ class SchemaTests(TransactionTestCase): ...@@ -2138,22 +2135,20 @@ class SchemaTests(TransactionTestCase):
"condition": "", "condition": "",
} }
) )
if connection.features.uppercases_column_names: self.assertIn(expected_constraint_name, self.get_constraints(model._meta.db_table))
constraint_name = constraint_name.upper()
self.assertIn(constraint_name, self.get_constraints(model._meta.db_table))
editor.alter_field(model, get_field(db_index=True), field, strict=True) editor.alter_field(model, get_field(db_index=True), field, strict=True)
self.assertNotIn(constraint_name, self.get_constraints(model._meta.db_table)) self.assertNotIn(expected_constraint_name, self.get_constraints(model._meta.db_table))
constraint_name = "CamelCaseUniqConstraint" constraint_name = 'CamelCaseUniqConstraint'
expected_constraint_name = identifier_converter(constraint_name)
editor.execute(editor._create_unique_sql(model, [field.column], constraint_name)) editor.execute(editor._create_unique_sql(model, [field.column], constraint_name))
if connection.features.uppercases_column_names: self.assertIn(expected_constraint_name, self.get_constraints(model._meta.db_table))
constraint_name = constraint_name.upper()
self.assertIn(constraint_name, self.get_constraints(model._meta.db_table))
editor.alter_field(model, get_field(unique=True), field, strict=True) editor.alter_field(model, get_field(unique=True), field, strict=True)
self.assertNotIn(constraint_name, self.get_constraints(model._meta.db_table)) self.assertNotIn(expected_constraint_name, self.get_constraints(model._meta.db_table))
if editor.sql_foreign_key_constraint: if editor.sql_foreign_key_constraint:
constraint_name = "CamelCaseFKConstraint" constraint_name = 'CamelCaseFKConstraint'
expected_constraint_name = identifier_converter(constraint_name)
fk_sql = editor.sql_foreign_key_constraint % { fk_sql = editor.sql_foreign_key_constraint % {
"column": editor.quote_name(column), "column": editor.quote_name(column),
"to_table": editor.quote_name(table), "to_table": editor.quote_name(table),
...@@ -2170,11 +2165,9 @@ class SchemaTests(TransactionTestCase): ...@@ -2170,11 +2165,9 @@ class SchemaTests(TransactionTestCase):
"constraint": constraint_sql, "constraint": constraint_sql,
} }
) )
if connection.features.uppercases_column_names: self.assertIn(expected_constraint_name, self.get_constraints(model._meta.db_table))
constraint_name = constraint_name.upper()
self.assertIn(constraint_name, self.get_constraints(model._meta.db_table))
editor.alter_field(model, get_field(Author, CASCADE, field_class=ForeignKey), field, strict=True) editor.alter_field(model, get_field(Author, CASCADE, field_class=ForeignKey), field, strict=True)
self.assertNotIn(constraint_name, self.get_constraints(model._meta.db_table)) self.assertNotIn(expected_constraint_name, self.get_constraints(model._meta.db_table))
def test_add_field_use_effective_default(self): def test_add_field_use_effective_default(self):
""" """
...@@ -2491,11 +2484,7 @@ class SchemaTests(TransactionTestCase): ...@@ -2491,11 +2484,7 @@ class SchemaTests(TransactionTestCase):
new_field.set_attributes_from_name('weight') new_field.set_attributes_from_name('weight')
with connection.schema_editor() as editor: with connection.schema_editor() as editor:
editor.alter_field(Author, old_field, new_field, strict=True) editor.alter_field(Author, old_field, new_field, strict=True)
self.assertEqual(self.get_constraints_for_column(Author, 'weight'), ['schema_author_weight_587740f9'])
expected = 'schema_author_weight_587740f9'
if connection.features.uppercases_column_names:
expected = expected.upper()
self.assertEqual(self.get_constraints_for_column(Author, 'weight'), [expected])
# Remove db_index=True to drop index. # Remove db_index=True to drop index.
with connection.schema_editor() as editor: with connection.schema_editor() as editor:
......
...@@ -113,11 +113,10 @@ class SelectForUpdateTests(TransactionTestCase): ...@@ -113,11 +113,10 @@ class SelectForUpdateTests(TransactionTestCase):
)) ))
features = connections['default'].features features = connections['default'].features
if features.select_for_update_of_column: if features.select_for_update_of_column:
expected = ['"select_for_update_person"."id"', '"select_for_update_country"."id"'] expected = ['select_for_update_person"."id', 'select_for_update_country"."id']
else: else:
expected = ['"select_for_update_person"', '"select_for_update_country"'] expected = ['select_for_update_person', 'select_for_update_country']
if features.uppercases_column_names: expected = [connection.ops.quote_name(value) for value in expected]
expected = [value.upper() for value in expected]
self.assertTrue(self.has_for_update_sql(ctx.captured_queries, of=expected)) self.assertTrue(self.has_for_update_sql(ctx.captured_queries, of=expected))
@skipUnlessDBFeature('has_select_for_update_of') @skipUnlessDBFeature('has_select_for_update_of')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment