Skip to content

Commit d3e746a

Browse files
dvarrazzofelixxm
authored andcommitted
Refs #33308 -- Added get_type_oids() hook and simplified registering type handlers on PostgreSQL.
1 parent 149b55f commit d3e746a

File tree

2 files changed

+27
-33
lines changed

2 files changed

+27
-33
lines changed

django/contrib/postgres/signals.py

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,16 @@
11
import functools
22

33
import psycopg2
4-
from psycopg2 import ProgrammingError
54
from psycopg2.extras import register_hstore
65

76
from django.db import connections
87
from django.db.backends.base.base import NO_DB_ALIAS
98

109

11-
@functools.lru_cache
12-
def get_hstore_oids(connection_alias):
13-
"""Return hstore and hstore array OIDs."""
10+
def get_type_oids(connection_alias, type_name):
1411
with connections[connection_alias].cursor() as cursor:
1512
cursor.execute(
16-
"SELECT t.oid, typarray "
17-
"FROM pg_type t "
18-
"JOIN pg_namespace ns ON typnamespace = ns.oid "
19-
"WHERE typname = 'hstore'"
13+
"SELECT oid, typarray FROM pg_type WHERE typname = %s", (type_name,)
2014
)
2115
oids = []
2216
array_oids = []
@@ -26,43 +20,42 @@ def get_hstore_oids(connection_alias):
2620
return tuple(oids), tuple(array_oids)
2721

2822

23+
@functools.lru_cache
24+
def get_hstore_oids(connection_alias):
25+
"""Return hstore and hstore array OIDs."""
26+
return get_type_oids(connection_alias, "hstore")
27+
28+
2929
@functools.lru_cache
3030
def get_citext_oids(connection_alias):
31-
"""Return citext array OIDs."""
32-
with connections[connection_alias].cursor() as cursor:
33-
cursor.execute("SELECT typarray FROM pg_type WHERE typname = 'citext'")
34-
return tuple(row[0] for row in cursor)
31+
"""Return citext and citext array OIDs."""
32+
return get_type_oids(connection_alias, "citext")
3533

3634

3735
def register_type_handlers(connection, **kwargs):
3836
if connection.vendor != "postgresql" or connection.alias == NO_DB_ALIAS:
3937
return
4038

41-
try:
42-
oids, array_oids = get_hstore_oids(connection.alias)
39+
oids, array_oids = get_hstore_oids(connection.alias)
40+
# Don't register handlers when hstore is not available on the database.
41+
#
42+
# If someone tries to create an hstore field it will error there. This is
43+
# necessary as someone may be using PSQL without extensions installed but
44+
# be using other features of contrib.postgres.
45+
#
46+
# This is also needed in order to create the connection in order to install
47+
# the hstore extension.
48+
if oids:
4349
register_hstore(
4450
connection.connection, globally=True, oid=oids, array_oid=array_oids
4551
)
46-
except ProgrammingError:
47-
# Hstore is not available on the database.
48-
#
49-
# If someone tries to create an hstore field it will error there.
50-
# This is necessary as someone may be using PSQL without extensions
51-
# installed but be using other features of contrib.postgres.
52-
#
53-
# This is also needed in order to create the connection in order to
54-
# install the hstore extension.
55-
pass
5652

57-
try:
58-
citext_oids = get_citext_oids(connection.alias)
53+
oids, citext_oids = get_citext_oids(connection.alias)
54+
# Don't register handlers when citext is not available on the database.
55+
#
56+
# The same comments in the above call to register_hstore() also apply here.
57+
if oids:
5958
array_type = psycopg2.extensions.new_array_type(
6059
citext_oids, "citext[]", psycopg2.STRING
6160
)
6261
psycopg2.extensions.register_type(array_type, None)
63-
except ProgrammingError:
64-
# citext is not available on the database.
65-
#
66-
# The same comments in the except block of the above call to
67-
# register_hstore() also apply here.
68-
pass

tests/postgres_tests/test_signals.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ def test_hstore_values(self):
3434
self.assertOIDs(array_oids)
3535

3636
def test_citext_values(self):
37-
oids = get_citext_oids(connection.alias)
37+
oids, citext_oids = get_citext_oids(connection.alias)
3838
self.assertOIDs(oids)
39+
self.assertOIDs(citext_oids)
3940

4041
def test_register_type_handlers_no_db(self):
4142
"""Registering type handlers for the nodb connection does nothing."""

0 commit comments

Comments
 (0)