From a5fd594ea428e3e8c11a632b1e3fd47df0cec2ab Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Wed, 29 Nov 2017 15:28:10 +0000 Subject: [PATCH] Collect rowcount in executemany even when discarding results Closes #633. --- NEWS | 4 +++- psycopg/pqpath.c | 3 ++- tests/test_cursor.py | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 3ed5ca72..280e1552 100644 --- a/NEWS +++ b/NEWS @@ -5,10 +5,12 @@ What's new in psycopg 2.7.4 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Fixed Solaris 10 support (:ticket:`#532`). -- Fixed `!MinTimeLoggingCursor` on Python 3 (:ticket:`#609`). +- Fixed `~psycopg2.extras.MinTimeLoggingCursor` on Python 3 (:ticket:`#609`). - Fixed parsing of array of points as floats (:ticket:`#613`). - Fixed `~psycopg2.__libpq_version__` building with libpq >= 10.1 (:ticket:`632`). +- Fixed `~cursor.rowcount` after `~cursor.executemany()` with :sql:`RETURNING` statements + (:ticket:`633`). - Wheel packages compiled against PostgreSQL 10.1 libpq and OpenSSL 1.0.2m. diff --git a/psycopg/pqpath.c b/psycopg/pqpath.c index a4235d1d..204a6b00 100644 --- a/psycopg/pqpath.c +++ b/psycopg/pqpath.c @@ -1952,8 +1952,9 @@ pq_fetch(cursorObject *curs, int no_result) } else { Dprintf("pq_fetch: got tuples, discarding them"); + /* TODO: is there any case in which PQntuples == PQcmdTuples? */ + _read_rowcount(curs); CLEARPGRES(curs->pgres); - curs->rowcount = -1; ex = 0; } break; diff --git a/tests/test_cursor.py b/tests/test_cursor.py index 10b8d71e..580cf9b1 100755 --- a/tests/test_cursor.py +++ b/tests/test_cursor.py @@ -592,6 +592,20 @@ class CursorTests(ConnectingTestCase): self.assertEqual(victim_conn.closed, 2) + @skip_before_postgres(8, 2) + def test_rowcount_on_executemany_returning(self): + cur = self.conn.cursor() + cur.execute("create table execmany(id serial primary key, data int)") + cur.executemany( + "insert into execmany (data) values (%s)", + [(i,) for i in range(4)]) + self.assertEqual(cur.rowcount, 4) + + cur.executemany( + "insert into execmany (data) values (%s) returning data", + [(i,) for i in range(5)]) + self.assertEqual(cur.rowcount, 5) + def test_suite(): return unittest.TestLoader().loadTestsFromName(__name__)