]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Gracefully degrade unsupported types with asyncpg
authorGord Thompson <gord@gordthompson.com>
Tue, 2 Nov 2021 22:16:50 +0000 (16:16 -0600)
committerGord Thompson <gord@gordthompson.com>
Tue, 2 Nov 2021 23:40:55 +0000 (17:40 -0600)
Fixes: #7284
Modify the on_connect() method of PGDialect_asyncpg to
gracefully degrade unsupported types instead of throwing a
ValueError. Useful for third-party dialects that derive
from PGDialect_asyncpg but whose databases do not support
all types (e.g., CockroachDB supports JSONB but not JSON).

Change-Id: Ibb7cc8c3de632d27b9716a93d83956a590b2a2b0

doc/build/changelog/unreleased_14/7284.rst [new file with mode: 0644]
lib/sqlalchemy/dialects/postgresql/asyncpg.py

diff --git a/doc/build/changelog/unreleased_14/7284.rst b/doc/build/changelog/unreleased_14/7284.rst
new file mode 100644 (file)
index 0000000..fb05488
--- /dev/null
@@ -0,0 +1,11 @@
+.. change::
+    :tags: asyncpg, usecase
+    :tickets: 7284
+    :versions: 2.0.0b1
+
+    Modified the asyncpg dialect to gracefully degrade types that are
+    not supported by PostgreSQL work-alike databases. For example,
+    CockroachDB supports JSONB but not JSON. Third-party dialects that
+    are derived from ``PGDialect_asyncpg`` will no longer have to
+    work around ValueError being raised by trying to register a codec
+    for an unsupported type.
index 3d195e691ae9b1aaf688ba4843d63b816c98c9a8..4e968a9b62b852922cfc57ff490652c45cd268b0 100644 (file)
@@ -870,6 +870,8 @@ class PGDialect_asyncpg(PGDialect):
 
     use_native_uuid = True
 
+    _exclude_type_codecs = util.EMPTY_SET
+
     colspecs = util.update_copy(
         PGDialect.colspecs,
         {
@@ -1022,21 +1024,34 @@ class PGDialect_asyncpg(PGDialect):
 
             See https://github.com/MagicStack/asyncpg/issues/623 for reference
             on why it's set up this way.
+
+            Also, see https://github.com/sqlalchemy/sqlalchemy/issues/7284 for
+            the rationale behind adding self._exclude_type_codecs
             """
-            await conn._connection.set_type_codec(
-                "json",
-                encoder=str.encode,
-                decoder=_json_decoder,
-                schema="pg_catalog",
-                format="binary",
-            )
-            await conn._connection.set_type_codec(
-                "jsonb",
-                encoder=_jsonb_encoder,
-                decoder=_jsonb_decoder,
-                schema="pg_catalog",
-                format="binary",
-            )
+
+            if "json" not in self._exclude_type_codecs:
+                try:
+                    await conn._connection.set_type_codec(
+                        "json",
+                        encoder=str.encode,
+                        decoder=_json_decoder,
+                        schema="pg_catalog",
+                        format="binary",
+                    )
+                except ValueError:
+                    self._exclude_type_codecs |= {"json"}
+
+            if "jsonb" not in self._exclude_type_codecs:
+                try:
+                    await conn._connection.set_type_codec(
+                        "jsonb",
+                        encoder=_jsonb_encoder,
+                        decoder=_jsonb_decoder,
+                        schema="pg_catalog",
+                        format="binary",
+                    )
+                except ValueError:
+                    self._exclude_type_codecs |= {"jsonb"}
 
         def connect(conn):
             conn.await_(_setup_type_codecs(conn))