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)
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):
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)