Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

[1.1.X] Fixed #12234 -- Create additional indexes that use the approp…

…riate operation class for PostgreSQL `varchar` and `text` columns when `db_index=True`.

Backport of r11912 from trunk.


git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.1.X@11913 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 281114d2095608c93a00df2fc55a72f7cd5c2fcf 1 parent d10f976
Justin Bronn authored December 19, 2009
39  django/db/backends/postgresql/creation.py
@@ -34,3 +34,42 @@ def sql_table_creation_suffix(self):
34 34
         if settings.TEST_DATABASE_CHARSET:
35 35
             return "WITH ENCODING '%s'" % settings.TEST_DATABASE_CHARSET
36 36
         return ''
  37
+
  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 = ''
  51
+
  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)
  59
+
  60
+            output = [get_index_sql('%s_%s' % (db_table, f.column))]
  61
+
  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 = []
  75
+        return output
15  docs/ref/databases.txt
@@ -80,6 +80,21 @@ You should also audit your existing code for any instances of this behavior
80 80
 before enabling this feature. It's faster, but it provides less automatic
81 81
 protection for multi-call operations.
82 82
 
  83
+Indexes for ``varchar`` and ``text`` columns
  84
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  85
+.. versionadded:: 1.1.2
  86
+
  87
+When specifying ``db_index=True`` on your model fields, Django typically
  88
+outputs a single ``CREATE INDEX`` statement.  However, if the database type
  89
+for the field is either ``varchar`` or ``text`` (e.g., used by ``CharField``,
  90
+``FileField``, and ``TextField``), then Django will create
  91
+an additional index that uses an appropriate `PostgreSQL operator class`_
  92
+for the column.  The extra index is necessary to correctly perfrom
  93
+lookups that use the ``LIKE`` operator in their SQL, as is done with the
  94
+``contains`` and ``startswith`` lookup types.
  95
+
  96
+.. _PostgreSQL operator class: http://www.postgresql.org/docs/8.4/static/indexes-opclass.html
  97
+
83 98
 .. _mysql-notes:
84 99
 
85 100
 MySQL notes

0 notes on commit 281114d

Please sign in to comment.
Something went wrong with that request. Please try again.