Ticket #2495: 2495-against-13302.diff

File 2495-against-13302.diff, 8.2 KB (added by Honza Král, 14 years ago)

another approach to the problem, including rework of #12234

  • django/db/backends/creation.py

    commit 645f5dda46705b4c403f2cab0ff634abf92d92d8
    Author: Honza Kral <honza.kral@gmail.com>
    Date:   Thu May 27 17:35:32 2010 +0200
    
        fixed #2495
    
    diff --git a/django/db/backends/creation.py b/django/db/backends/creation.py
    index 492ac1e..06df548 100644
    a b class BaseDatabaseCreation(object):  
    253253            output.extend(self.sql_indexes_for_field(model, f, style))
    254254        return output
    255255
    256     def sql_indexes_for_field(self, model, f, style):
    257         "Return the CREATE INDEX SQL statements for a single model field"
     256    def compile_sql_index_for_field(self, db_table, f, style, tablespace_sql):
     257        "Compile CREATE INDEX SQL statements for sql_indexes_for_field"
    258258        from django.db.backends.util import truncate_name
    259259
     260        qn = self.connection.ops.quote_name
     261        index_name = '%s_%s' % (db_table, self._digest(f.column))
     262        return [style.SQL_KEYWORD('CREATE INDEX') + ' ' +
     263                style.SQL_TABLE(qn(truncate_name(index_name, self.connection.ops.max_name_length()))) + ' ' +
     264                style.SQL_KEYWORD('ON') + ' ' +
     265                style.SQL_TABLE(qn(db_table)) + ' ' +
     266                "(%s)" % style.SQL_FIELD(qn(f.column)) +
     267                "%s;" % tablespace_sql]
     268
     269    def sql_indexes_for_field(self, model, f, style):
     270        "Return the CREATE INDEX SQL statements for a single model field"
    260271        if f.db_index and not f.unique:
    261             qn = self.connection.ops.quote_name
    262272            tablespace = f.db_tablespace or model._meta.db_tablespace
    263273            if tablespace:
    264274                sql = self.connection.ops.tablespace_sql(tablespace)
    class BaseDatabaseCreation(object):  
    268278                    tablespace_sql = ''
    269279            else:
    270280                tablespace_sql = ''
    271             i_name = '%s_%s' % (model._meta.db_table, self._digest(f.column))
    272             output = [style.SQL_KEYWORD('CREATE INDEX') + ' ' +
    273                 style.SQL_TABLE(qn(truncate_name(i_name, self.connection.ops.max_name_length()))) + ' ' +
    274                 style.SQL_KEYWORD('ON') + ' ' +
    275                 style.SQL_TABLE(qn(model._meta.db_table)) + ' ' +
    276                 "(%s)" % style.SQL_FIELD(qn(f.column)) +
    277                 "%s;" % tablespace_sql]
     281            output = self.compile_sql_index_for_field(model._meta.db_table, f, style, tablespace_sql)
    278282        else:
    279283            output = []
    280284        return output
  • django/db/backends/mysql/creation.py

    diff --git a/django/db/backends/mysql/creation.py b/django/db/backends/mysql/creation.py
    index 8b026a9..a3ef8df 100644
    a b class DatabaseCreation(BaseDatabaseCreation):  
    6363                field.rel.to._meta.db_table, field.rel.to._meta.pk.column)
    6464            ]
    6565        return table_output, deferred
     66
     67    def compile_sql_index_for_field(self, db_table, f, style, tablespace_sql):
     68        """
     69        Adds a  prefix length to the TextField which is currently represented
     70        by MySQL's 'longtext' type -- which requires a prefix-length parameter
     71        in order to install an index.
     72
     73        Use largest possible value allowed - 255 characters.
     74        """
     75        from django.db.backends.util import truncate_name
     76
     77        qn = self.connection.ops.quote_name
     78        index_name = '%s_%s' % (db_table, self._digest(f.column))
     79
     80        if f.db_type() == self.data_types['TextField']:
     81            field_name = style.SQL_FIELD(qn(f.column)) + '(255)'
     82        else:
     83            field_name = style.SQL_FIELD(qn(f.column))
     84
     85        return [style.SQL_KEYWORD('CREATE INDEX') + ' ' +
     86                style.SQL_TABLE(qn(truncate_name(index_name, self.connection.ops.max_name_length()))) + ' ' +
     87                style.SQL_KEYWORD('ON') + ' ' +
     88                style.SQL_TABLE(qn(db_table)) + ' ' +
     89                "(%s)" % field_name +
     90                "%s;" % tablespace_sql]
     91
  • django/db/backends/postgresql/creation.py

    diff --git a/django/db/backends/postgresql/creation.py b/django/db/backends/postgresql/creation.py
    index af26d0b..3db1506 100644
    a b class DatabaseCreation(BaseDatabaseCreation):  
    3535            return "WITH ENCODING '%s'" % self.connection.settings_dict['TEST_CHARSET']
    3636        return ''
    3737
    38     def sql_indexes_for_field(self, model, f, style):
    39         if f.db_index and not f.unique:
    40             qn = self.connection.ops.quote_name
    41             db_table = model._meta.db_table
    42             tablespace = f.db_tablespace or model._meta.db_tablespace
    43             if tablespace:
    44                 sql = self.connection.ops.tablespace_sql(tablespace)
    45                 if sql:
    46                     tablespace_sql = ' ' + sql
    47                 else:
    48                     tablespace_sql = ''
    49             else:
    50                 tablespace_sql = ''
     38    def compile_sql_index_for_field(self, db_table, f, style, tablespace_sql):
     39        def _get_index_sql(index_name, opclass=''):
     40            from django.db.backends.util import truncate_name
    5141
    52             def get_index_sql(index_name, opclass=''):
    53                 return (style.SQL_KEYWORD('CREATE INDEX') + ' ' +
    54                         style.SQL_TABLE(qn(index_name)) + ' ' +
    55                         style.SQL_KEYWORD('ON') + ' ' +
    56                         style.SQL_TABLE(qn(db_table)) + ' ' +
    57                         "(%s%s)" % (style.SQL_FIELD(qn(f.column)), opclass) +
    58                         "%s;" % tablespace_sql)
     42            qn = self.connection.ops.quote_name
     43            return (style.SQL_KEYWORD('CREATE INDEX') + ' ' +
     44                style.SQL_TABLE(qn(truncate_name(index_name, self.connection.ops.max_name_length()))) + ' ' +
     45                style.SQL_KEYWORD('ON') + ' ' +
     46                style.SQL_TABLE(qn(db_table)) + ' ' +
     47                "(%s%s)" % (style.SQL_FIELD(qn(f.column)), opclass) +
     48                "%s;" % tablespace_sql)
    5949
    60             output = [get_index_sql('%s_%s' % (db_table, f.column))]
     50        output = [_get_index_sql('%s_%s' % (db_table, f.column))]
    6151
    62             # Fields with database column types of `varchar` and `text` need
    63             # a second index that specifies their operator class, which is
    64             # needed when performing correct LIKE queries outside the
    65             # C locale. See #12234.
    66             db_type = f.db_type()
    67             if db_type.startswith('varchar'):
    68                 output.append(get_index_sql('%s_%s_like' % (db_table, f.column),
    69                                             ' varchar_pattern_ops'))
    70             elif db_type.startswith('text'):
    71                 output.append(get_index_sql('%s_%s_like' % (db_table, f.column),
    72                                             ' text_pattern_ops'))
    73         else:
    74             output = []
     52        # Fields with database column types of `varchar` and `text` need
     53        # a second index that specifies their operator class, which is
     54        # needed when performing correct LIKE queries outside the
     55        # C locale. See #12234.
     56        db_type = f.db_type()
     57        if db_type.startswith('varchar'):
     58            output.append(_get_index_sql('%s_%s_like' % (db_table, f.column),
     59                                        ' varchar_pattern_ops'))
     60        elif db_type.startswith('text'):
     61            output.append(_get_index_sql('%s_%s_like' % (db_table, f.column),
     62                                        ' text_pattern_ops'))
    7563        return output
  • new file tests/regressiontests/bug2495/models.py

    diff --git a/tests/regressiontests/bug2495/__init__.py b/tests/regressiontests/bug2495/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/regressiontests/bug2495/models.py b/tests/regressiontests/bug2495/models.py
    new file mode 100644
    index 0000000..91661b3
    - +  
     1from unittest import TestCase
     2
     3from django.db import models, connection
     4
     5class IndexedTextModel(models.Model):
     6    indexed_text = models.TextField(db_index=True)
     7
     8class TestTextFieldIndices(TestCase):
     9    def test_indexed_text_has_an_index(self):
     10        try:
     11            indexes = connection.introspection.get_indexes(connection.cursor(), IndexedTextModel._meta.db_table)
     12        except NotImplementedError:
     13            indexes = {}
     14        assert 'indexed_text' in indexes
     15
Back to Top