]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
fix: add lookup of dumpers by varchar, name oid
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Thu, 8 Dec 2022 14:35:55 +0000 (14:35 +0000)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sat, 10 Dec 2022 13:01:15 +0000 (13:01 +0000)
Fix #452

docs/news.rst
psycopg/psycopg/types/string.py
psycopg_c/psycopg_c/types/string.pyx

index d29de2da7ed7081e0c50adb06bc08af79ca58723..d5a99a1dd4fed5af9d50c48be8566abf4d49b2e1 100644 (file)
@@ -17,6 +17,7 @@ Psycopg 3.1.5 (unreleased)
   (:ticket:`#422`).
 - Fix `Cursor.rownumber` to return `!None` when the result has no row to fetch
   (:ticket:`#437`).
+- Fix `Copy.set_types()` used with `varchar` and `name` types (:ticket:`#452`).
 
 
 Current release
index c15c3926a6401ec2f9dfe293fe5e80dfb6cd5364..cd5360dba428a8860743460250df3f1195c38f5f 100644 (file)
@@ -24,10 +24,14 @@ class _BaseStrDumper(Dumper):
         self._encoding = enc if enc != "ascii" else "utf-8"
 
 
-class StrBinaryDumper(_BaseStrDumper):
+class _StrBinaryDumper(_BaseStrDumper):
+    """
+    Base class to dump a Python strings to a Postgres text type, in binary format.
+
+    Subclasses shall specify the oids of real types (text, varchar, name...).
+    """
 
     format = Format.BINARY
-    oid = postgres.types["text"].oid
 
     def dump(self, obj: str) -> bytes:
         # the server will raise DataError subclass if the string contains 0x00
@@ -35,6 +39,12 @@ class StrBinaryDumper(_BaseStrDumper):
 
 
 class _StrDumper(_BaseStrDumper):
+    """
+    Base class to dump a Python strings to a Postgres text type, in text format.
+
+    Subclasses shall specify the oids of real types (text, varchar, name...).
+    """
+
     def dump(self, obj: str) -> bytes:
         if "\x00" in obj:
             raise DataError("PostgreSQL text fields cannot contain NUL (0x00) bytes")
@@ -42,6 +52,24 @@ class _StrDumper(_BaseStrDumper):
             return obj.encode(self._encoding)
 
 
+# The next are concrete dumpers, each one specifying the oid they dump to.
+
+
+class StrBinaryDumper(_StrBinaryDumper):
+
+    oid = postgres.types["text"].oid
+
+
+class StrBinaryDumperVarchar(_StrBinaryDumper):
+
+    oid = postgres.types["varchar"].oid
+
+
+class StrBinaryDumperName(_StrBinaryDumper):
+
+    oid = postgres.types["name"].oid
+
+
 class StrDumper(_StrDumper):
     """
     Dumper for strings in text format to the text oid.
@@ -55,6 +83,16 @@ class StrDumper(_StrDumper):
     oid = postgres.types["text"].oid
 
 
+class StrDumperVarchar(_StrDumper):
+
+    oid = postgres.types["varchar"].oid
+
+
+class StrDumperName(_StrDumper):
+
+    oid = postgres.types["name"].oid
+
+
 class StrDumperUnknown(_StrDumper):
     """
     Dumper for strings in text format to the unknown oid.
@@ -62,7 +100,7 @@ class StrDumperUnknown(_StrDumper):
     This dumper is the default dumper for strings and allows to use Python
     strings to represent almost every data type. In a few places, however, the
     unknown oid is not accepted (for instance in variadic functions such as
-    'concat()'). In that case either a cast on the placeholder ('%s::text) or
+    'concat()'). In that case either a cast on the placeholder ('%s::text') or
     the StrTextDumper should be used.
     """
 
@@ -167,9 +205,13 @@ def register_default_adapters(context: AdaptContext) -> None:
     # registered becomes the default for each type. Usually, binary is the
     # default dumper. For text we use the text dumper as default because it
     # plays the role of unknown, and it can be cast automatically to other
-    # types. However, before that, we register a dumper with the text oid,
-    # which will be used when a text dumper is looked up by oid.
+    # types. However, before that, we register dumper with 'text', 'varchar',
+    # 'name' oids, which will be used when a text dumper is looked up by oid.
+    adapters.register_dumper(str, StrBinaryDumperName)
+    adapters.register_dumper(str, StrBinaryDumperVarchar)
     adapters.register_dumper(str, StrBinaryDumper)
+    adapters.register_dumper(str, StrDumperName)
+    adapters.register_dumper(str, StrDumperVarchar)
     adapters.register_dumper(str, StrDumper)
     adapters.register_dumper(str, StrDumperUnknown)
 
index cae6a4b5f95291fe6fb29ab3eb849c538640efde..da18b015a25564f5282be789a8940433bb5205cb 100644 (file)
@@ -68,13 +68,29 @@ cdef class _BaseStrDumper(CDumper):
         return size
 
 
-@cython.final
-cdef class StrBinaryDumper(_BaseStrDumper):
+cdef class _StrBinaryDumper(_BaseStrDumper):
 
     format = PQ_BINARY
+
+
+@cython.final
+cdef class StrBinaryDumper(_StrBinaryDumper):
+
     oid = oids.TEXT_OID
 
 
+@cython.final
+cdef class StrBinaryDumperVarchar(_StrBinaryDumper):
+
+    oid = oids.VARCHAR_OID
+
+
+@cython.final
+cdef class StrBinaryDumperName(_StrBinaryDumper):
+
+    oid = oids.NAME_OID
+
+
 cdef class _StrDumper(_BaseStrDumper):
 
     format = PQ_TEXT
@@ -97,6 +113,18 @@ cdef class StrDumper(_StrDumper):
     oid = oids.TEXT_OID
 
 
+@cython.final
+cdef class StrDumperVarchar(_StrDumper):
+
+    oid = oids.VARCHAR_OID
+
+
+@cython.final
+cdef class StrDumperName(_StrDumper):
+
+    oid = oids.NAME_OID
+
+
 @cython.final
 cdef class StrDumperUnknown(_StrDumper):
     pass