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.
* has_patch: 1 => 0
* type: Bug => Cleanup/optimization
* stage: Unreviewed => Accepted
Comment:
I'm in favor. Please check again the `Has patch` box when a GitHub PR is
available.
--
Ticket URL: <https://code.djangoproject.com/ticket/31615#comment:1>
Comment (by minusf):
please have a look at this one:
https://github.com/django/django/pull/12952
git got the better of me :/
--
Ticket URL: <https://code.djangoproject.com/ticket/31615#comment:3>
* needs_better_patch: 0 => 1
* needs_tests: 0 => 1
--
Ticket URL: <https://code.djangoproject.com/ticket/31615#comment:4>
* owner: nobody => minusf
* needs_better_patch: 1 => 0
* status: new => assigned
* needs_tests: 1 => 0
* stage: Accepted => Ready for checkin
--
Ticket URL: <https://code.djangoproject.com/ticket/31615#comment:5>
* status: assigned => closed
* resolution: => fixed
Comment:
In [changeset:"d693a086def21d843c03ec3f5b5e697ed2463d45" d693a086]:
{{{
#!CommitTicketReference repository=""
revision="d693a086def21d843c03ec3f5b5e697ed2463d45"
Fixed #31615 -- Made migrations skip extension operations if not needed.
- Don't try to create an existing extension.
- Don't try to drop a nonexistent extension.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/31615#comment:7>
Comment (by Mariusz Felisiak <felisiak.mariusz@…>):
In [changeset:"f3ed42c8ad3757e7238bf2f326532f5b129aa102" f3ed42c8]:
{{{
#!CommitTicketReference repository=""
revision="f3ed42c8ad3757e7238bf2f326532f5b129aa102"
Refs #31615 -- Improved creating extension docs.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/31615#comment:6>
Comment (by Mariusz Felisiak <felisiak.mariusz@…>):
In [changeset:"a79d0c8c81847e9ccde42e406bb5b411bab4214a" a79d0c8c]:
{{{
#!CommitTicketReference repository=""
revision="a79d0c8c81847e9ccde42e406bb5b411bab4214a"
[3.1.x] Refs #31615 -- Improved creating extension docs.
Backport of f3ed42c8ad3757e7238bf2f326532f5b129aa102 from master
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/31615#comment:8>
Comment (by Mariusz Felisiak <felisiak.mariusz@…>):
In [changeset:"22a59c01c00cf9fbefaee0e8e67fab82bbaf1fd2" 22a59c01]:
{{{
#!CommitTicketReference repository=""
revision="22a59c01c00cf9fbefaee0e8e67fab82bbaf1fd2"
Refs #31615 -- Added EXISTS clauses to extension operations.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/31615#comment:9>