]> 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>
Tue, 14 Oct 2025 00:13:28 +0000 (02:13 +0200)
psycopg/psycopg/_py_transformer.py
tests/test_copy.py
tests/test_copy_async.py

index 7328c8fe3eaa2fff0151077683d1a49427289d56..ff2375b189aa672089531bdf28e0322bd05abb83 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 7ba54c8957758303d1c1c3903dfb62ce5bc71d8d..c71fba61c27eaa347f565c96376325f4aa9c9474 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 63b73d70fe60ec18e25277a7153f7b2517a77c2d..1031148968f9a27c1d8e00bae4ba31422c97f4cc 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)