#31615: Do not fail migration if postgresql extension is already installed and
user
is not superuser
-------------------------------------+-------------------------------------
Reporter: minusf | Owner: nobody
Type: Bug | Status: new
Component: | Version: 3.0
Migrations | Keywords: migration extension
Severity: Normal | postgresql
Triage Stage: | Has patch: 1
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 1
UI/UX: 0 |
-------------------------------------+-------------------------------------
Currently Django facilitates installing postgres extensions using
migration operations:
https://docs.djangoproject.com/en/3.0/ref/contrib/postgres/operations/
But having a superuser is a tall order in certain environments, and the
manual helpfully points out:
If the Django database user doesn’t have superuser privileges, you’ll have
to create the extension outside of Django migrations with a user that has
the appropriate privileges.
This is fairly often the case with Salt and other orchestration systems.
However having a non-superuser will break any migrations using these
operations because unfortunately `CREATE EXTENSION` even with `IF NOT
EXISTS` still requires superuser privileges... In other words, if the
extension is already in place, the migration will fail...
I think a failsafe like this around CREATE/DROP EXTENSION would make the
migrations more robust and user friendly.
{{{
diff --git a/django/contrib/postgres/operations.py
b/django/contrib/postgres/operations.py
index 0bb131ddf2..46fc11f63f 100644
--- a/django/contrib/postgres/operations.py
+++ b/django/contrib/postgres/operations.py
@@ -21,7 +21,13 @@ class CreateExtension(Operation):
not router.allow_migrate(schema_editor.connection.alias,
app_label)
):
return
- schema_editor.execute("CREATE EXTENSION IF NOT EXISTS %s" %
schema_editor.quote_name(self.name))
+
+ cur = schema_editor.connection.cursor()
+ cur.execute("SELECT * FROM pg_extension WHERE extname = %s",
[self.name])
+ if not cur.fetchone():
+ schema_editor.execute(
+ "CREATE EXTENSION IF NOT EXISTS %s" %
schema_editor.quote_name(self.name)
+ )
# Clear cached, stale oids.
get_hstore_oids.cache_clear()
get_citext_oids.cache_clear()
@@ -33,7 +39,13 @@ class CreateExtension(Operation):
def database_backwards(self, app_label, schema_editor, from_state,
to_state):
if not router.allow_migrate(schema_editor.connection.alias,
app_label):
return
- schema_editor.execute("DROP EXTENSION %s" %
schema_editor.quote_name(self.name))
+
+ cur = schema_editor.connection.cursor()
+ cur.execute("SELECT * FROM pg_extension WHERE extname = %s",
[self.name])
+ if cur.fetchone():
+ schema_editor.execute(
+ "DROP EXTENSION %s" % schema_editor.quote_name(self.name)
+ )
# Clear cached, stale oids.
get_hstore_oids.cache_clear()
get_citext_oids.cache_clear()
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/31615>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/049.d4a7512325c3974cbc631d30dc90716f%40djangoproject.com.