1
0
mirror of https://github.com/django/django.git synced 2025-10-26 15:16:09 +00:00

Fixed #25412 -- Fixed missing PostgreSQL index on Char/TextField when using AlterField.

Thanks to Emanuele Palazzetti for the help.
This commit is contained in:
Federico Frenguelli
2015-11-07 17:08:03 +01:00
committed by Tim Graham
parent cf546e11ac
commit 3a36c80795
4 changed files with 121 additions and 17 deletions

View File

@@ -23,25 +23,33 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
return output
for field in model._meta.local_fields:
db_type = field.db_type(connection=self.connection)
if db_type is not None and (field.db_index or field.unique):
# Fields with database column types of `varchar` and `text` need
# a second index that specifies their operator class, which is
# needed when performing correct LIKE queries outside the
# C locale. See #12234.
#
# The same doesn't apply to array fields such as varchar[size]
# and text[size], so skip them.
if '[' in db_type:
continue
if db_type.startswith('varchar'):
output.append(self._create_index_sql(
model, [field], suffix='_like', sql=self.sql_create_varchar_index))
elif db_type.startswith('text'):
output.append(self._create_index_sql(
model, [field], suffix='_like', sql=self.sql_create_text_index))
like_index_statement = self._create_like_index_sql(model, field)
if like_index_statement is not None:
output.append(like_index_statement)
return output
def _create_like_index_sql(self, model, field):
"""
Return the statement to create an index with varchar operator pattern
when the column type is 'varchar' or 'text', otherwise return None.
"""
db_type = field.db_type(connection=self.connection)
if db_type is not None and (field.db_index or field.unique):
# Fields with database column types of `varchar` and `text` need
# a second index that specifies their operator class, which is
# needed when performing correct LIKE queries outside the
# C locale. See #12234.
#
# The same doesn't apply to array fields such as varchar[size]
# and text[size], so skip them.
if '[' in db_type:
return None
if db_type.startswith('varchar'):
return self._create_index_sql(model, [field], suffix='_like', sql=self.sql_create_varchar_index)
elif db_type.startswith('text'):
return self._create_index_sql(model, [field], suffix='_like', sql=self.sql_create_text_index)
return None
def _alter_column_type_sql(self, table, old_field, new_field, new_type):
"""
Makes ALTER TYPE with SERIAL make sense.
@@ -94,3 +102,23 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
return super(DatabaseSchemaEditor, self)._alter_column_type_sql(
table, old_field, new_field, new_type
)
def _alter_field(self, model, old_field, new_field, old_type, new_type,
old_db_params, new_db_params, strict=False):
super(DatabaseSchemaEditor, self)._alter_field(
model, old_field, new_field, old_type, new_type, old_db_params,
new_db_params, strict,
)
# Added an index? Create any PostgreSQL-specific indexes.
if ((not old_field.db_index and new_field.db_index) or (not old_field.unique and new_field.unique)):
like_index_statement = self._create_like_index_sql(model, new_field)
if like_index_statement is not None:
self.execute(like_index_statement)
# Removed an index? Drop any PostgreSQL-specific indexes.
if ((not new_field.db_index and old_field.db_index) or (not new_field.unique and old_field.unique)):
index_to_remove = self._create_index_name(model, [old_field.column], suffix='_like')
index_names = self._constraint_names(model, [old_field.column], index=True)
for index_name in index_names:
if index_name == index_to_remove:
self.execute(self._delete_constraint_sql(self.sql_delete_index, model, index_name))