]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Fixes(#7561) Add support for postgres.UUID literal_binds compilation
authorJosé Duarte <duarte@dystematic.com>
Thu, 13 Jan 2022 22:20:06 +0000 (17:20 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 14 Jan 2022 21:42:16 +0000 (16:42 -0500)
Added string rendering to the :class:`.postgresql.UUID` datatype, so that
stringifying a statement with "literal_binds" that uses this type will
render an appropriate string value for the PostgreSQL backend. Pull request
courtesy José Duarte.

Fixes: #7561
Closes: #7563
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/7563
Pull-request-sha: cf6fe73265342d7884a940c4b3a34c9552113ec3

Change-Id: I4b162bdcdce2293a90683e36da54e4a891a3c684

doc/build/changelog/unreleased_14/7561.rst [new file with mode: 0644]
lib/sqlalchemy/dialects/postgresql/base.py
test/dialect/postgresql/test_types.py

diff --git a/doc/build/changelog/unreleased_14/7561.rst b/doc/build/changelog/unreleased_14/7561.rst
new file mode 100644 (file)
index 0000000..18ea110
--- /dev/null
@@ -0,0 +1,8 @@
+.. change::
+    :tags: usecase, postgresql
+    :tickets: 7561
+
+    Added string rendering to the :class:`.postgresql.UUID` datatype, so that
+    stringifying a statement with "literal_binds" that uses this type will
+    render an appropriate string value for the PostgreSQL backend. Pull request
+    courtesy José Duarte.
index bf8812ae5455d79f036515f2f216694166e4e314..4f3e297ef557d47431b3fe274c6370b26ba08ecd 100644 (file)
@@ -1410,7 +1410,6 @@ from ...types import SMALLINT
 from ...types import TEXT
 from ...types import VARCHAR
 
-
 IDX_USING = re.compile(r"^(?:btree|hash|gist|gin|[\w_]+)$", re.I)
 
 RESERVED_WORDS = set(
@@ -1751,6 +1750,24 @@ class UUID(sqltypes.TypeEngine):
         else:
             return None
 
+    def literal_processor(self, dialect):
+        if self.as_uuid:
+
+            def process(value):
+                if value is not None:
+                    value = "'%s'::UUID" % value
+                return value
+
+            return process
+        else:
+
+            def process(value):
+                if value is not None:
+                    value = "'%s'" % value
+                return value
+
+            return process
+
 
 PGUuid = UUID
 
index e8c18acb04b0b528e67c45e390ca48e992f94867..991b0ed9d4a01a2723de3a7cd67a913e41b9c803 100644 (file)
@@ -48,6 +48,7 @@ from sqlalchemy.dialects.postgresql import TSTZRANGE
 from sqlalchemy.exc import CompileError
 from sqlalchemy.orm import declarative_base
 from sqlalchemy.orm import Session
+from sqlalchemy.sql import bindparam
 from sqlalchemy.sql import operators
 from sqlalchemy.sql import sqltypes
 from sqlalchemy.testing import fixtures
@@ -929,10 +930,10 @@ class NumericInterpretationTest(fixtures.TestBase):
 
     def test_numeric_codes(self):
         from sqlalchemy.dialects.postgresql import (
+            base,
             pg8000,
             psycopg2,
             psycopg2cffi,
-            base,
         )
 
         dialects = (
@@ -1420,9 +1421,11 @@ class ArrayTest(AssertsCompiledSQL, fixtures.TestBase):
         argnames="with_enum, using_aggregate_order_by",
     )
     def test_array_agg_specific(self, with_enum, using_aggregate_order_by):
-        from sqlalchemy.dialects.postgresql import aggregate_order_by
-        from sqlalchemy.dialects.postgresql import array_agg
-        from sqlalchemy.dialects.postgresql import ENUM
+        from sqlalchemy.dialects.postgresql import (
+            ENUM,
+            aggregate_order_by,
+            array_agg,
+        )
 
         element_type = ENUM if with_enum else Integer
         expr = (
@@ -2785,6 +2788,33 @@ class UUIDTest(fixtures.TestBase):
     def test_uuid_array(self, datatype, value1, value2, connection):
         self.test_round_trip(datatype, value1, value2, connection)
 
+    @testing.combinations(
+        (
+            "not_as_uuid",
+            postgresql.UUID(as_uuid=False),
+            str(uuid.uuid4()),
+        ),
+        (
+            "as_uuid",
+            postgresql.UUID(as_uuid=True),
+            uuid.uuid4(),
+        ),
+        id_="iaa",
+        argnames="datatype, value1",
+    )
+    def test_uuid_literal(self, datatype, value1, connection):
+        v1 = connection.execute(
+            select(
+                bindparam(
+                    "key",
+                    value=value1,
+                    literal_execute=True,
+                    type_=datatype,
+                )
+            ),
+        )
+        eq_(v1.fetchone()[0], value1)
+
 
 class HStoreTest(AssertsCompiledSQL, fixtures.TestBase):
     __dialect__ = "postgresql"