]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Don't change asyncpg's "char" codec
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 16 Sep 2020 12:26:14 +0000 (08:26 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 16 Sep 2020 14:44:37 +0000 (10:44 -0400)
This codec was used to ensure the "pg_attribute.generated"
column comes back as a string and not bytes, matching how
other PG drivers treat this datatype.   However, this breaks
asyncpg's internal implementation of set_type_codec going forward
and the "char" datatype is actually a bytes in any case.
So at the moment it appears psycopg2/pg8000 are broken for mis-treatment
of the datatype and asyncpg is broken in that it was allowing
us to change a codec that it appears to rely upon internally.

Fixes: #5586
Change-Id: I937eba315904721aa4e2726b95432910a8affe5f

lib/sqlalchemy/dialects/postgresql/asyncpg.py
lib/sqlalchemy/dialects/postgresql/base.py

index 780e238449cb28c18fa66fb0c5e0009f0a877fbd..6fa1dd78beee228c8ade143015083e13639ec3c7 100644 (file)
@@ -486,28 +486,13 @@ class AsyncAdapt_asyncpg_connection:
     async def _setup_type_codecs(self):
         """set up type decoders at the asyncpg level.
 
-        this is first to accommodate the "char" value of
-        pg_catalog.pg_attribute.attgenerated being returned as bytes.
-        Even though the doc at
-        https://magicstack.github.io/asyncpg/current/usage.html#type-conversion
-        claims "char" is returned as "str", it looks like this is actually
-        the 'bpchar' datatype, blank padded.  'char' seems to be some
-        more obscure type (oid 18) and asyncpg codes this to bytea:
-        https://github.com/MagicStack/asyncpg/blob/master/asyncpg/protocol/
-        codecs/pgproto.pyx#L26
-
-        all the other drivers treat this as a string.
+        these are set_type_codec() calls to normalize
+        There was a tentative decoder for the "char" datatype here
+        to have it return strings however this type is actually a binary
+        type that other drivers are likely mis-interpreting.
 
         """
 
-        await self._connection.set_type_codec(
-            "char",
-            schema="pg_catalog",
-            encoder=lambda value: value,
-            decoder=lambda value: value,
-            format="text",
-        )
-
     def _handle_exception(self, error):
         if not isinstance(error, AsyncAdapt_asyncpg_dbapi.Error):
             exception_mapping = self.dbapi._asyncpg_error_translate
index 5e81586b49cefeadeea7dee55de2d3743ed5fe7f..8786938668560c2ea0b8710c3b302c2edc28fcd3 100644 (file)
@@ -3423,10 +3423,14 @@ class PGDialect(default.DefaultDialect):
             )
             coltype = sqltypes.NULLTYPE
 
-        # If a zero byte (''), then not a generated column.
-        # Otherwise, s = stored. (Other values might be added in the future.)
-        if generated:
-            computed = dict(sqltext=default, persisted=generated == "s")
+        # If a zero byte or blank string depending on driver (is also absent
+        # for older PG versions), then not a generated column. Otherwise, s =
+        # stored. (Other values might be added in the future.)
+        #
+        if generated not in (None, "", b"\x00"):
+            computed = dict(
+                sqltext=default, persisted=generated in ("s", b"s")
+            )
             default = None
         else:
             computed = None