69 lines
2.6 KiB
Python
69 lines
2.6 KiB
Python
from django.db import migrations, transaction
|
|
from django.db.migrations.operations.base import Operation
|
|
from django.db.utils import InternalError, OperationalError, ProgrammingError
|
|
|
|
|
|
class SafeExtensionOperation(Operation):
|
|
reversible = True
|
|
|
|
def state_forwards(self, app_label, state):
|
|
pass
|
|
|
|
def database_forwards(self, app_label, schema_editor, from_state, to_state):
|
|
if schema_editor.connection.vendor != 'postgresql':
|
|
return
|
|
try:
|
|
with transaction.atomic():
|
|
try:
|
|
schema_editor.execute('CREATE EXTENSION IF NOT EXISTS %s SCHEMA public' % self.name)
|
|
except (OperationalError, ProgrammingError):
|
|
# OperationalError if the extension is not available
|
|
# ProgrammingError in case of denied permission
|
|
RunSQLIfExtension.extensions_installed = False
|
|
except InternalError:
|
|
# InternalError (current transaction is aborted, commands ignored
|
|
# until end of transaction block) would be raised when django-
|
|
# tenant-schemas set search_path.
|
|
RunSQLIfExtension.extensions_installed = False
|
|
|
|
def database_backwards(self, app_label, schema_editor, from_state, to_state):
|
|
try:
|
|
with transaction.atomic():
|
|
schema_editor.execute('DROP EXTENSION IF EXISTS %s' % self.name)
|
|
except InternalError:
|
|
# Raised when other objects depend on the extension. This happens in a multitenant
|
|
# context, where extension in installed in schema "public" but referenced in others (via
|
|
# public.gist_trgm_ops). In this case, do nothing, as the query should be successful
|
|
# when last tenant is processed.
|
|
pass
|
|
|
|
|
|
class RunSQLIfExtension(migrations.RunSQL):
|
|
extensions_installed = True
|
|
|
|
def __getattribute__(self, name):
|
|
if name == 'sql' and not self.extensions_installed:
|
|
return migrations.RunSQL.noop
|
|
return object.__getattribute__(self, name)
|
|
|
|
|
|
class TrigramExtension(SafeExtensionOperation):
|
|
name = 'pg_trgm'
|
|
|
|
|
|
class Migration(migrations.Migration):
|
|
dependencies = [
|
|
('custom_user', '0023_index_username'),
|
|
]
|
|
|
|
operations = [
|
|
TrigramExtension(),
|
|
RunSQLIfExtension(
|
|
sql=[
|
|
'CREATE INDEX IF NOT EXISTS custom_user_user_email_trgm_idx ON custom_user_user USING gist'
|
|
' (LOWER(email) public.gist_trgm_ops)'
|
|
],
|
|
reverse_sql=['DROP INDEX custom_user_user_email_trgm_idx'],
|
|
),
|
|
]
|