]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
fix: consistent error passing a row with mismatched size to copy
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Mon, 13 Oct 2025 13:30:04 +0000 (15:30 +0200)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Mon, 13 Oct 2025 23:54:10 +0000 (01:54 +0200)
psycopg/psycopg/_py_transformer.py
tests/test_copy.py
tests/test_copy_async.py

index a41332b9d57d3f0bf503ba9bb9ca0181920d6494..41ffbbc5b73437676a26e2d97452216214754d80 100644 (file)
@@ -178,6 +178,10 @@ class Transformer(AdaptContext):
         # which case self.types and self.formats are set to sequences of the
         # right size.
         if self._row_dumpers:
+            if len(self._row_dumpers) != nparams:
+                raise e.DataError(
+                    f"expected {len(self._row_dumpers)} values in row, got {nparams}"
+                )
             for i in range(nparams):
                 if (param := params[i]) is not None:
                     out[i] = self._row_dumpers[i].dump(param)
index ccd9dadd9152144920a6768b103a19174eeffd63..a0cad5aaef4ca54fe03f89681d37058b61740a0a 100644 (file)
@@ -133,16 +133,16 @@ def test_set_types(conn, format):
 
 @pytest.mark.parametrize("format", pq.Format)
 @pytest.mark.parametrize("use_set_types", [True, False])
-def test_segfault_rowlen_mismatch(conn, format, use_set_types):
-    samples = [[123, 456], [123, 456, 789]]
+def test_rowlen_mismatch(conn, format, use_set_types):
+    samples = [["foo", "bar"], ["foo", "bar", "baz"]]
     cur = conn.cursor()
-    ensure_table(cur, "id serial primary key, data integer, data2 integer")
-    with pytest.raises(Exception):
+    ensure_table(cur, "id serial primary key, data text, data2 text")
+    with pytest.raises(psycopg.DataError):
         with cur.copy(
             f"copy copy_in (data, data2) from stdin (format {format.name})"
         ) as copy:
             if use_set_types:
-                copy.set_types(["integer", "integer"])
+                copy.set_types(["text", "text"])
             for row in samples:
                 copy.write_row(row)
 
index 775d4d9cebe6088bc13e8f20f00750f9644f75e6..70d30dbda9d4951962b9a7a7ba85a0b589835d4e 100644 (file)
@@ -137,16 +137,16 @@ async def test_set_types(aconn, format):
 
 @pytest.mark.parametrize("format", pq.Format)
 @pytest.mark.parametrize("use_set_types", [True, False])
-async def test_segfault_rowlen_mismatch(aconn, format, use_set_types):
-    samples = [[123, 456], [123, 456, 789]]
+async def test_rowlen_mismatch(aconn, format, use_set_types):
+    samples = [["foo", "bar"], ["foo", "bar", "baz"]]
     cur = aconn.cursor()
-    await ensure_table_async(cur, "id serial primary key, data integer, data2 integer")
-    with pytest.raises(Exception):
+    await ensure_table_async(cur, "id serial primary key, data text, data2 text")
+    with pytest.raises(psycopg.DataError):
         async with cur.copy(
             f"copy copy_in (data, data2) from stdin (format {format.name})"
         ) as copy:
             if use_set_types:
-                copy.set_types(["integer", "integer"])
+                copy.set_types(["text", "text"])
             for row in samples:
                 await copy.write_row(row)