]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Improve the GUID typedecorator example
authorFederico Caselli <cfederico87@gmail.com>
Mon, 11 Sep 2023 20:57:20 +0000 (22:57 +0200)
committerFederico Caselli <cfederico87@gmail.com>
Tue, 12 Sep 2023 18:51:58 +0000 (20:51 +0200)
Change-Id: I92909b1262f994a3ff0dd201bc87612ff1d37822
References: #10336

doc/build/core/custom_types.rst
setup.cfg

index d084b428c89655e889a3df6d719f74cd15b29a08..6ae9e066ace7711f3843b485fe78a0f5f8dfbd9a 100644 (file)
@@ -171,12 +171,20 @@ denormalize::
 Backend-agnostic GUID Type
 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-Receives and returns Python uuid() objects.  Uses the PG UUID type
-when using PostgreSQL, CHAR(32) on other backends, storing them
-in stringified hex format.   Can be modified to store
-binary in CHAR(16) if desired::
-
+.. note:: Since version 2.0 the built-in :class:`_types.Uuid` type that
+    behaves similarly should be preferred. This example is presented
+    just as an example of a type decorator that recieves and returns
+    python objects.
+
+Receives and returns Python uuid() objects.  
+Uses the PG UUID type when using PostgreSQL, UNIQUEIDENTIFIER when using MSSQL,
+CHAR(32) on other backends, storing them in stringified format.
+The ``GUIDHyphens`` version stores the value with hyphens instead of just the hex
+string, using a CHAR(36) type::
+
+    from operator import attrgetter
     from sqlalchemy.types import TypeDecorator, CHAR
+    from sqlalchemy.dialects.mssql import UNIQUEIDENTIFIER
     from sqlalchemy.dialects.postgresql import UUID
     import uuid
 
@@ -184,31 +192,34 @@ binary in CHAR(16) if desired::
     class GUID(TypeDecorator):
         """Platform-independent GUID type.
 
-        Uses PostgreSQL's UUID type, otherwise uses
-        CHAR(32), storing as stringified hex values.
+        Uses PostgreSQL's UUID type or MSSQL's UNIQUEIDENTIFIER,
+        otherwise uses CHAR(32), storing as stringified hex values.
 
         """
 
         impl = CHAR
         cache_ok = True
 
+        _default_type = CHAR(32)
+        _uuid_as_str = attrgetter("hex")
+
         def load_dialect_impl(self, dialect):
             if dialect.name == "postgresql":
                 return dialect.type_descriptor(UUID())
+            elif dialect.name == "mssql":
+                return dialect.type_descriptor(UNIQUEIDENTIFIER())
             else:
-                return dialect.type_descriptor(CHAR(32))
+                return dialect.type_descriptor(self._default_type)
 
         def process_bind_param(self, value, dialect):
             if value is None:
                 return value
-            elif dialect.name == "postgresql":
+            elif dialect.name in ("postgresql", "mssql"):
                 return str(value)
             else:
                 if not isinstance(value, uuid.UUID):
-                    return "%.32x" % uuid.UUID(value).int
-                else:
-                    # hexstring
-                    return "%.32x" % value.int
+                    value = uuid.UUID(value)
+                return self._uuid_as_str(value)
 
         def process_result_value(self, value, dialect):
             if value is None:
@@ -218,6 +229,18 @@ binary in CHAR(16) if desired::
                     value = uuid.UUID(value)
                 return value
 
+
+    class GUIDHyphens(GUID):
+        """Platform-independent GUID type.
+
+        Uses PostgreSQL's UUID type or MSSQL's UNIQUEIDENTIFIER,
+        otherwise uses CHAR(36), storing as stringified uuid values.
+
+        """
+
+        _default_type = CHAR(36)
+        _uuid_as_str = str
+
 Linking Python ``uuid.UUID`` to the Custom Type for ORM mappings
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
index 5c68605d08fa986398beef0d03654af13684c83a..bcfa98116bfdd75433e09dd69790e8e698af6e5a 100644 (file)
--- a/setup.cfg
+++ b/setup.cfg
@@ -170,7 +170,7 @@ mariadb = mariadb+mysqldb://scott:tiger@127.0.0.1:3306/test
 mariadb_connector = mariadb+mariadbconnector://scott:tiger@127.0.0.1:3306/test
 mssql = mssql+pyodbc://scott:tiger^5HHH@mssql2017:1433/test?driver=ODBC+Driver+18+for+SQL+Server&TrustServerCertificate=yes
 pymssql = mssql+pymssql://scott:tiger^5HHH@mssql2017:1433/test
-docker_mssql = mssql+pyodbc://scott:tiger^5HHH@127.0.0.1:1433/test?driver=ODBC+Driver+17+for+SQL+Server
+docker_mssql = mssql+pyodbc://scott:tiger^5HHH@127.0.0.1:1433/test?driver=ODBC+Driver+18+for+SQL+Server
 oracle = oracle+cx_oracle://scott:tiger@oracle18c/xe
 cxoracle = oracle+cx_oracle://scott:tiger@oracle18c/xe
 oracledb = oracle+oracledb://scott:tiger@oracle18c/xe