Skip to content

Commit

Permalink
add postgres create index concurrently support
Browse files Browse the repository at this point in the history
  • Loading branch information
erebus1 committed Mar 26, 2018
1 parent b3bf2dd commit 9b4ba10
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 3 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,32 @@ It is up to you to ensure that the expressions are otherwise valid SQL and have
Using [Django's query expressions](https://docs.djangoproject.com/en/1.11/ref/models/expressions/) that check the syntax and generate valid SQL
for either database is planned for a future version.

To use concurrent index creation in postgres, you should add index in a regular way,
but after makemigration, change generated migration:
- atomic=False,
- add arg: concurrently=True

```python
class Migration(migrations.Migration):
atomic = False

operations = [
migrations.AddIndex(
model_name='dog',
index=partial_index.PartialIndex(
fields=[b'id'],
name='dog_id_c78984_partial', unique=True,
concurrently=True
),
),
]

```
## Version History

### 0.4.1.dev
add Postgres Create Index Concurrently support

### 0.4.0 (latest)
* Add support for Django 2.0.

Expand Down
9 changes: 7 additions & 2 deletions partial_index/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,17 @@ class PartialIndex(Index):
# The "partial" suffix is 4 letters longer than the default "idx".
max_name_length = 34
sql_create_index = {
'postgresql': 'CREATE%(unique)s INDEX %(name)s ON %(table)s%(using)s (%(columns)s)%(extra)s WHERE %(where)s',
'postgresql': 'CREATE%(unique)s INDEX%(concurrently)s %(name)s ON %(table)s%(using)s (%(columns)s)%(extra)s WHERE %(where)s;',
'sqlite': 'CREATE%(unique)s INDEX %(name)s ON %(table)s%(using)s (%(columns)s) WHERE %(where)s',
}

# Mutable default fields=[] looks wrong, but it's copied from super class.
def __init__(self, fields=[], name=None, unique=None, where='', where_postgresql='', where_sqlite=''):
def __init__(self, fields=[], name=None, unique=None, where='', where_postgresql='',
where_sqlite='', concurrently=False):
if unique not in [True, False]:
raise ValueError('Unique must be True or False')
if concurrently not in [True, False]:
raise ValueError('Unique must be True or False')
if where:
if where_postgresql or where_sqlite:
raise ValueError('If providing a single where predicate, must not provide where_postgresql or where_sqlite')
Expand All @@ -44,6 +47,7 @@ def __init__(self, fields=[], name=None, unique=None, where='', where_postgresql
raise ValueError('If providing a separate where_postgresql and where_sqlite, then they must be different.' +
'If the same expression works for both, just use single where.')
self.unique = unique
self.concurrently = concurrently
self.where = where
self.where_postgresql = where_postgresql
self.where_sqlite = where_sqlite
Expand Down Expand Up @@ -99,6 +103,7 @@ def get_sql_create_template_values(self, model, schema_editor, using):

# PartialIndex updates:
parameters['unique'] = ' UNIQUE' if self.unique else ''
parameters['concurrently'] = ' CONCURRENTLY' if self.concurrently else ''
# Note: the WHERE predicate is not yet checked for syntax or field names, and is inserted into the CREATE INDEX query unescaped.
# This is bad for usability, but is not a security risk, as the string cannot come from user input.
vendor = self.get_valid_vendor(schema_editor)
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
setup(
name='django-partial-index',
packages=['partial_index'],
version='0.4.0',
version='0.4.1.dev',
description='PostgreSQL and SQLite partial indexes for Django models',
long_description=open('README.md').read(),
author='Mattias Linnap',
Expand Down

0 comments on commit 9b4ba10

Please sign in to comment.