From: Daniele Varrazzo Date: Mon, 13 Oct 2025 13:30:04 +0000 (+0200) Subject: fix: consistent error passing a row with mismatched size to copy X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8244668751676eddb4ea1d28ca044e57a7e16e9f;p=thirdparty%2Fpsycopg.git fix: consistent error passing a row with mismatched size to copy --- diff --git a/psycopg/psycopg/_py_transformer.py b/psycopg/psycopg/_py_transformer.py index a41332b9d..41ffbbc5b 100644 --- a/psycopg/psycopg/_py_transformer.py +++ b/psycopg/psycopg/_py_transformer.py @@ -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) diff --git a/tests/test_copy.py b/tests/test_copy.py index ccd9dadd9..a0cad5aae 100644 --- a/tests/test_copy.py +++ b/tests/test_copy.py @@ -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) diff --git a/tests/test_copy_async.py b/tests/test_copy_async.py index 775d4d9ce..70d30dbda 100644 --- a/tests/test_copy_async.py +++ b/tests/test_copy_async.py @@ -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)