]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
Fixed escaping of a few chars in composite dumping
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sat, 5 Dec 2020 04:05:34 +0000 (04:05 +0000)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sat, 5 Dec 2020 04:15:33 +0000 (04:15 +0000)
psycopg3/psycopg3/types/composite.py
tests/types/test_composite.py

index 49580d4acbc9a266817c2fa32fe4ca93010a7339..f26739e619dc0afb472782196c302008fa607d79 100644 (file)
@@ -155,7 +155,9 @@ class TupleDumper(Dumper):
 
             dumper = self._tx.get_dumper(item, Format.TEXT)
             ad = dumper.dump(item)
-            if self._re_needs_quotes.search(ad):
+            if not ad:
+                ad = b'""'
+            elif self._re_needs_quotes.search(ad):
                 ad = b'"' + self._re_escape.sub(br"\1\1", ad) + b'"'
 
             parts.append(ad)
@@ -165,13 +167,8 @@ class TupleDumper(Dumper):
 
         return b"".join(parts)
 
-    _re_needs_quotes = re.compile(
-        br"""(?xi)
-          ^$            # the empty string
-        | [",\\\s]      # or a char to escape
-        """
-    )
-    _re_escape = re.compile(br"([\"])")
+    _re_needs_quotes = re.compile(br'[",\\\s()]')
+    _re_escape = re.compile(br"([\\\"])")
 
 
 class BaseCompositeLoader(Loader):
index 1ecb9c0c99b38176b6f96a926755109e0d28debb..a35f065631df621beaa1133226013c115b47e1b1 100644 (file)
@@ -173,6 +173,20 @@ async def test_fetch_info_async(aconn, testcomp, name, fields):
         assert info.fields[i].type_oid == builtins[t].oid
 
 
+@pytest.mark.parametrize("fmt_in", [Format.TEXT, Format.BINARY])
+def test_dump_composite_all_chars(conn, fmt_in, testcomp):
+    if fmt_in == Format.BINARY:
+        pytest.xfail("binary composite dumper not implemented")
+    ph = "%s" if fmt_in == Format.TEXT else "%b"
+    cur = conn.cursor()
+    for i in range(1, 256):
+        (res,) = cur.execute(
+            f"select row(chr(%s::int), 1, 1.0)::testcomp = {ph}::testcomp",
+            (i, (chr(i), 1, 1.0)),
+        ).fetchone()
+        assert res is True
+
+
 @pytest.mark.parametrize("fmt_out", [Format.TEXT, Format.BINARY])
 def test_load_composite(conn, testcomp, fmt_out):
     cur = conn.cursor(format=fmt_out)