From 177cc1c330f3cc0626156e3cf3f6d7f00d2d906c Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Mon, 25 Jan 2021 14:23:09 +0100 Subject: [PATCH] misc: add migration to fix absence of immutable_unaccent() (#50462) --- .../0033_recreate_immutable_unaccent.py | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 src/authentic2/migrations/0033_recreate_immutable_unaccent.py diff --git a/src/authentic2/migrations/0033_recreate_immutable_unaccent.py b/src/authentic2/migrations/0033_recreate_immutable_unaccent.py new file mode 100644 index 00000000..798a58cf --- /dev/null +++ b/src/authentic2/migrations/0033_recreate_immutable_unaccent.py @@ -0,0 +1,76 @@ +# Generated by Django 2.2.17 on 2021-01-25 13:21 + +from __future__ import unicode_literals + +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 UnaccentExtension(SafeExtensionOperation): + name = 'unaccent' + + +class TrigramExtension(SafeExtensionOperation): + name = 'pg_trgm' + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentic2', '0032_initialize_search_vectors'), + ] + + operations = [ + TrigramExtension(), + UnaccentExtension(), + RunSQLIfExtension( + sql=["CREATE OR REPLACE FUNCTION public.immutable_unaccent(text) RETURNS varchar AS $$ " + "SELECT public.unaccent('public.unaccent',$1::text); $$ LANGUAGE 'sql' IMMUTABLE"], + reverse_sql=['DROP FUNCTION IF EXISTS public.immutable_unaccent(text)'] + ), + ] -- 2.29.2