| Bug #117548 | mysql/connector python fetchmany() has an off by one bug when argument given as 1 | ||
|---|---|---|---|
| Submitted: | 23 Feb 23:07 | Modified: | 4 Jul 21:14 |
| Reporter: | Mike Bayer | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | Connector / Python | Severity: | S1 (Critical) |
| Version: | 9.2.0 | OS: | Any |
| Assigned to: | CPU Architecture: | Any | |
[24 Feb 7:48]
MySQL Verification Team
Hello Mike Bayer, Thank you for the report and test case. Verified as described. regards, Umesh
[25 Feb 16:56]
Oscar Pacheco
Posted by developer: Dear all, After further verification, we detected the issue is exclusive of the c-extension implementation. For those users impacted by this bug, you may consider the following workarounds while the bug gets fixed: 1. Use buffered cursors. 2. If a slight performance hit is not a concern, use the pure-python implementation. Regards.
[28 May 12:33]
Souma Kanti Ghosh
Posted by developer: Hello Mike, Thank you for raising this bug. Cheers, Souma Kanti
[4 Jul 21:14]
Daniel So
Posted by developer: Added the following entry to the Connector/Python 9.4.0 changelog: "When using the Connector/Python C Extension with an unbuffered server-side cursor, fetchmany(1) failed to fetch more results after reading the second row in the result set."

Description: Re-evaluating mysql-connector-python to be supported in SQLAlchemy, using a server side cursor fetchmany(1) never returns an empty list. Run demonstration program below might have appeared with bz#97830 How to repeat: from mysql import connector connection = connector.connect(user="scott", password="tiger", host="mysql80", database="test") cursor = connection.cursor(buffered=False) cursor.execute("Drop table if exists test") cursor.execute("create table test (id integer)") cursor.execute("insert into test (id) values (1), (2), (3), (4), (5)") cursor.execute("select * from test") while True: many = cursor.fetchmany(2) print(f"Fetchmany(2): {many}") if not many: break cursor.execute("select * from test") while True: many = cursor.fetchmany(1) print(f"Fetchmany(1): {many}") if not many: break for the fetchmany(2) case, output is correct: Fetchmany(2): [(1,), (2,)] Fetchmany(2): [(3,), (4,)] Fetchmany(2): [(5,)] Fetchmany(2): [] for the fetchmany(1) case, it gets stuck on [(2,)] and never exits: Fetchmany(1): [(1,)] Fetchmany(1): [(2,)] Fetchmany(1): [(2,)] Fetchmany(1): [(2,)] Fetchmany(1): [(2,)] ... turning on buffered mode also resolves, then we get the correct output Fetchmany(2): [(1,), (2,)] Fetchmany(2): [(3,), (4,)] Fetchmany(2): [(5,)] Fetchmany(2): [] Fetchmany(1): [(1,)] Fetchmany(1): [(2,)] Fetchmany(1): [(3,)] Fetchmany(1): [(4,)] Fetchmany(1): [(5,)] Fetchmany(1): [] The above program continuously returns [(2, )]