]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
Add an adaptation example for infinity date
authorDenis Laxalde <denis.laxalde@dalibo.com>
Thu, 29 Apr 2021 09:14:32 +0000 (11:14 +0200)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sun, 2 May 2021 00:15:11 +0000 (02:15 +0200)
Take from https://www.psycopg.org/articles/2020/11/24/psycopg3-adaptation/

docs/advanced/adapt.rst

index 3025dde16f26ac94c70a1e70d8b56dc7df12c68a..4d7296773ce08ef9fd8ccf90f987816739e0d03b 100644 (file)
@@ -57,9 +57,52 @@ configuration.
     subclass `!Dumper` or `!Loader` you should call the ``.register()`` on the
     class you created.
 
+For example, suppose you want to work with the "infinity" date which is
+available in PostgreSQL but not handled by Python:
+
+.. code:: python
+
+    >>> conn.execute("'infinity'::date").fetchone()
+    Traceback (most recent call last):
+       ...
+    psycopg3.DataError: Python date doesn't support years after 9999: got infinity
+
+One possibility would be to store Python's `datetime.date.max` to PostgreSQL
+infinity. For this, let's create a subclass for the dumper and the loader and
+register them in the working scope (globally or just on a connection or
+cursor):
+
+.. code:: python
+
+    from datetime import date
+
+    from psycopg3.oids import postgres_types as builtins
+    from psycopg3.types import DateLoader, DateDumper
+
+    class InfDateDumper(DateDumper):
+        def dump(self, obj):
+            if obj == date.max:
+                return b"infinity"
+            else:
+                return super().dump(obj)
+
+    class InfDateLoader(DateLoader):
+        def load(self, data):
+            if data == b"infinity":
+                return date.max
+            else:
+                return super().load(data)
+
+    InfDateDumper.register(date, cur)
+    InfDateLoader.register(builtins["date"].oid, cur)
+
+    cur.execute("SELECT %s::text, %s::text", [date(2020, 12, 31), date.max]).fetchone()
+    # ('2020-12-31', 'infinity')
+    cur.execute("select '2020-12-31'::date, 'infinity'::date").fetchone()
+    # (datetime.date(2020, 12, 31), datetime.date(9999, 12, 31))
+
 .. admonition:: TODO
 
-    - Example: infinity date customisation
     - Example: numeric to float