mirror of https://github.com/django/django.git
Fixed #27030 -- Added contrib.postgres.indexes.GinIndex.
This commit is contained in:
parent
236baa0f0e
commit
6e07ec3f65
|
@ -0,0 +1,12 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db.models import Index
|
||||||
|
|
||||||
|
__all__ = ['GinIndex']
|
||||||
|
|
||||||
|
|
||||||
|
class GinIndex(Index):
|
||||||
|
suffix = 'gin'
|
||||||
|
|
||||||
|
def create_sql(self, model, schema_editor):
|
||||||
|
return super(GinIndex, self).create_sql(model, schema_editor, using=' USING gin')
|
|
@ -880,6 +880,7 @@ class BaseDatabaseSchemaEditor(object):
|
||||||
return sql_create_index % {
|
return sql_create_index % {
|
||||||
"table": self.quote_name(model._meta.db_table),
|
"table": self.quote_name(model._meta.db_table),
|
||||||
"name": self.quote_name(self._create_index_name(model, columns, suffix=suffix)),
|
"name": self.quote_name(self._create_index_name(model, columns, suffix=suffix)),
|
||||||
|
"using": "",
|
||||||
"columns": ", ".join(self.quote_name(column) for column in columns),
|
"columns": ", ".join(self.quote_name(column) for column in columns),
|
||||||
"extra": tablespace_sql,
|
"extra": tablespace_sql,
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
||||||
sql_delete_sequence = "DROP SEQUENCE IF EXISTS %(sequence)s CASCADE"
|
sql_delete_sequence = "DROP SEQUENCE IF EXISTS %(sequence)s CASCADE"
|
||||||
sql_set_sequence_max = "SELECT setval('%(sequence)s', MAX(%(column)s)) FROM %(table)s"
|
sql_set_sequence_max = "SELECT setval('%(sequence)s', MAX(%(column)s)) FROM %(table)s"
|
||||||
|
|
||||||
|
sql_create_index = "CREATE INDEX %(name)s ON %(table)s%(using)s (%(columns)s)%(extra)s"
|
||||||
sql_create_varchar_index = "CREATE INDEX %(name)s ON %(table)s (%(columns)s varchar_pattern_ops)%(extra)s"
|
sql_create_varchar_index = "CREATE INDEX %(name)s ON %(table)s (%(columns)s varchar_pattern_ops)%(extra)s"
|
||||||
sql_create_text_index = "CREATE INDEX %(name)s ON %(table)s (%(columns)s text_pattern_ops)%(extra)s"
|
sql_create_text_index = "CREATE INDEX %(name)s ON %(table)s (%(columns)s text_pattern_ops)%(extra)s"
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ class Index(object):
|
||||||
self.name = 'D%s' % self.name[1:]
|
self.name = 'D%s' % self.name[1:]
|
||||||
return errors
|
return errors
|
||||||
|
|
||||||
def create_sql(self, model, schema_editor):
|
def create_sql(self, model, schema_editor, using=''):
|
||||||
fields = [model._meta.get_field(field_name) for field_name, order in self.fields_orders]
|
fields = [model._meta.get_field(field_name) for field_name, order in self.fields_orders]
|
||||||
tablespace_sql = schema_editor._get_index_tablespace_sql(model, fields)
|
tablespace_sql = schema_editor._get_index_tablespace_sql(model, fields)
|
||||||
quote_name = schema_editor.quote_name
|
quote_name = schema_editor.quote_name
|
||||||
|
@ -54,6 +54,7 @@ class Index(object):
|
||||||
'table': quote_name(model._meta.db_table),
|
'table': quote_name(model._meta.db_table),
|
||||||
'name': quote_name(self.name),
|
'name': quote_name(self.name),
|
||||||
'columns': ', '.join(columns),
|
'columns': ', '.join(columns),
|
||||||
|
'using': using,
|
||||||
'extra': tablespace_sql,
|
'extra': tablespace_sql,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ release. Some fields require higher versions.
|
||||||
fields
|
fields
|
||||||
forms
|
forms
|
||||||
functions
|
functions
|
||||||
|
indexes
|
||||||
lookups
|
lookups
|
||||||
operations
|
operations
|
||||||
search
|
search
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
=================================
|
||||||
|
PostgreSQL specific model indexes
|
||||||
|
=================================
|
||||||
|
|
||||||
|
.. module:: django.contrib.postgres.indexes
|
||||||
|
|
||||||
|
.. versionadded:: 1.11
|
||||||
|
|
||||||
|
The following are PostgreSQL specific :doc:`indexes </ref/models/indexes>`
|
||||||
|
available from the ``django.contrib.postgres.indexes`` module.
|
||||||
|
|
||||||
|
``GinIndex``
|
||||||
|
============
|
||||||
|
|
||||||
|
.. class:: GinIndex()
|
||||||
|
|
||||||
|
Creates a `gin index
|
||||||
|
<https://www.postgresql.org/docs/current/static/gin.html>`_.
|
||||||
|
|
||||||
|
To use this index, you need to activate the `btree_gin extension
|
||||||
|
<https://www.postgresql.org/docs/current/static/btree-gin.html>`_ on
|
||||||
|
PostgreSQL. You can install it using the
|
||||||
|
:class:`~django.contrib.postgres.operations.BtreeGinExtension` migration
|
||||||
|
operation.
|
|
@ -56,3 +56,8 @@ case, a descending index is created as a normal index.
|
||||||
The name of the index. If ``name`` isn't provided Django will auto-generate a
|
The name of the index. If ``name`` isn't provided Django will auto-generate a
|
||||||
name. For compatibility with different databases, index names cannot be longer
|
name. For compatibility with different databases, index names cannot be longer
|
||||||
than 30 characters and shouldn't start with a number (0-9) or underscore (_).
|
than 30 characters and shouldn't start with a number (0-9) or underscore (_).
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
For a list of PostgreSQL-specific indexes, see
|
||||||
|
:mod:`django.contrib.postgres.indexes`.
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
from django.contrib.postgres.indexes import GinIndex
|
||||||
|
from django.db import connection
|
||||||
|
|
||||||
|
from . import PostgreSQLTestCase
|
||||||
|
from .models import IntegerArrayModel
|
||||||
|
|
||||||
|
|
||||||
|
class GinIndexTests(PostgreSQLTestCase):
|
||||||
|
|
||||||
|
def test_repr(self):
|
||||||
|
index = GinIndex(fields=['title'])
|
||||||
|
self.assertEqual(repr(index), "<GinIndex: fields='title'>")
|
||||||
|
|
||||||
|
def test_eq(self):
|
||||||
|
index = GinIndex(fields=['title'])
|
||||||
|
same_index = GinIndex(fields=['title'])
|
||||||
|
another_index = GinIndex(fields=['author'])
|
||||||
|
self.assertEqual(index, same_index)
|
||||||
|
self.assertNotEqual(index, another_index)
|
||||||
|
|
||||||
|
def test_name_auto_generation(self):
|
||||||
|
index = GinIndex(fields=['field'])
|
||||||
|
index.set_name_with_model(IntegerArrayModel)
|
||||||
|
self.assertEqual(index.name, 'postgres_te_field_def2f8_gin')
|
||||||
|
|
||||||
|
def test_deconstruction(self):
|
||||||
|
index = GinIndex(fields=['title'], name='test_title_gin')
|
||||||
|
path, args, kwargs = index.deconstruct()
|
||||||
|
self.assertEqual(path, 'django.contrib.postgres.indexes.GinIndex')
|
||||||
|
self.assertEqual(args, ())
|
||||||
|
self.assertEqual(kwargs, {'fields': ['title'], 'name': 'test_title_gin'})
|
||||||
|
|
||||||
|
|
||||||
|
class SchemaTests(PostgreSQLTestCase):
|
||||||
|
|
||||||
|
def get_indexes(self, table):
|
||||||
|
"""
|
||||||
|
Get the indexes on the table using a new cursor.
|
||||||
|
"""
|
||||||
|
with connection.cursor() as cursor:
|
||||||
|
return connection.introspection.get_indexes(cursor, table)
|
||||||
|
|
||||||
|
def test_gin_index(self):
|
||||||
|
# Ensure the table is there and doesn't have an index.
|
||||||
|
self.assertNotIn('field', self.get_indexes(IntegerArrayModel._meta.db_table))
|
||||||
|
# Add the index
|
||||||
|
index = GinIndex(fields=['field'], name='integer_array_model_field_gin')
|
||||||
|
with connection.schema_editor() as editor:
|
||||||
|
editor.add_index(IntegerArrayModel, index)
|
||||||
|
self.assertIn('field', self.get_indexes(IntegerArrayModel._meta.db_table))
|
||||||
|
self.assertEqual(self.get_indexes(IntegerArrayModel._meta.db_table)['field']['type'], 'gin')
|
||||||
|
# Drop the index
|
||||||
|
with connection.schema_editor() as editor:
|
||||||
|
editor.remove_index(IntegerArrayModel, index)
|
||||||
|
self.assertNotIn('field', self.get_indexes(IntegerArrayModel._meta.db_table))
|
|
@ -1803,6 +1803,7 @@ class SchemaTests(TransactionTestCase):
|
||||||
editor.sql_create_index % {
|
editor.sql_create_index % {
|
||||||
"table": editor.quote_name(table),
|
"table": editor.quote_name(table),
|
||||||
"name": editor.quote_name(constraint_name),
|
"name": editor.quote_name(constraint_name),
|
||||||
|
"using": "",
|
||||||
"columns": editor.quote_name(column),
|
"columns": editor.quote_name(column),
|
||||||
"extra": "",
|
"extra": "",
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue