From 85857b6b59e1896f0a273c780e559c58c6cd6cc0 Mon Sep 17 00:00:00 2001 From: "utkarsh.arya@zomato.com" Date: Sat, 15 Nov 2025 23:00:31 +0000 Subject: [PATCH] Fix whitespace in CREATE INDEX SQL for index suffixes Ensure proper spacing before DESC and after opclasses in generated CREATE INDEX statements. This improves SQL readability and resolves formatting quirks introduced by previous fixes. Refs #30903. --- django/db/backends/ddl_references.py | 12 +++++++--- tests/indexes/tests.py | 35 ++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/django/db/backends/ddl_references.py b/django/db/backends/ddl_references.py index 44e49806f8..ba55de1df8 100644 --- a/django/db/backends/ddl_references.py +++ b/django/db/backends/ddl_references.py @@ -83,10 +83,14 @@ class Columns(TableColumns): def __str__(self): def col_str(column, idx): + col = self.quote_name(column) try: - return self.quote_name(column) + self.col_suffixes[idx] + suffix = self.col_suffixes[idx] + if suffix: + col = '{} {}'.format(col, suffix) except IndexError: - return self.quote_name(column) + pass + return col return ', '.join(col_str(column, idx) for idx, column in enumerate(self.columns)) @@ -114,7 +118,9 @@ class IndexColumns(Columns): # length as self.columns. col = '{} {}'.format(self.quote_name(column), self.opclasses[idx]) try: - col = '{} {}'.format(col, self.col_suffixes[idx]) + suffix = self.col_suffixes[idx] + if suffix: + col = '{} {}'.format(col, suffix) except IndexError: pass return col diff --git a/tests/indexes/tests.py b/tests/indexes/tests.py index 588feaddff..ae34b26509 100644 --- a/tests/indexes/tests.py +++ b/tests/indexes/tests.py @@ -75,6 +75,15 @@ class SchemaIndexesTests(TestCase): index_sql = connection.schema_editor()._model_indexes_sql(IndexTogetherSingleList) self.assertEqual(len(index_sql), 1) + def test_index_sql_whitespace_desc(self): + """Test that CREATE INDEX has proper whitespace before DESC.""" + editor = connection.schema_editor() + index = Index(fields=['-headline'], name='test_idx_desc') + sql = str(index.create_sql(Article, editor)) + # Should have space before DESC, not "headline"DESC + self.assertIn('"headline" DESC', sql) + self.assertNotIn('"headline"DESC', sql) + @skipIf(connection.vendor == 'postgresql', 'opclasses are PostgreSQL only') class SchemaIndexesNotPostgreSQLTests(TransactionTestCase): @@ -223,6 +232,32 @@ class SchemaIndexesPostgreSQLTests(TransactionTestCase): cursor.execute(self.get_opclass_query % indexname) self.assertCountEqual(cursor.fetchall(), [('text_pattern_ops', indexname)]) + def test_ops_class_whitespace(self): + """Test proper whitespace in CREATE INDEX with opclasses.""" + # Test ascending order (empty suffix) doesn't add trailing space + index_asc = Index( + name='test_ops_class_asc', + fields=['body'], + opclasses=['text_pattern_ops'], + ) + with connection.schema_editor() as editor: + sql = str(index_asc.create_sql(IndexedArticle2, editor)) + # Should not have trailing space after opclass + self.assertNotIn('text_pattern_ops )', sql) + self.assertIn('text_pattern_ops)', sql) + + # Test descending order has proper spacing + index_desc = Index( + name='test_ops_class_desc', + fields=['-body'], + opclasses=['text_pattern_ops'], + ) + with connection.schema_editor() as editor: + sql = str(index_desc.create_sql(IndexedArticle2, editor)) + # Should have space before DESC, no double spaces + self.assertIn('text_pattern_ops DESC', sql) + self.assertNotIn('text_pattern_ops DESC', sql) + @skipUnless(connection.vendor == 'mysql', 'MySQL tests') class SchemaIndexesMySQLTests(TransactionTestCase):