@@ -139,6 +139,45 @@ def test_rollback_cursor_consistency(self):
139
139
con .rollback ()
140
140
self .assertEqual (cur .fetchall (), [(1 ,), (2 ,), (3 ,)])
141
141
142
+ def test_multiple_cursors_and_iternext (self ):
143
+ # gh-94028: statements are cleared and reset in cursor iternext.
144
+
145
+ # Provoke the gh-94028 by using a cursor cache.
146
+ CURSORS = {}
147
+ def sql (cx , sql , * args ):
148
+ cu = cx .cursor ()
149
+ cu .execute (sql , args )
150
+ CURSORS [id (sql )] = cu
151
+ return cu
152
+
153
+ self .con1 .execute ("create table t(t)" )
154
+ sql (self .con1 , "insert into t values (?), (?), (?)" , "u1" , "u2" , "u3" )
155
+ self .con1 .commit ()
156
+
157
+ # On second connection, verify rows are visible, then delete them.
158
+ count = sql (self .con2 , "select count(*) from t" ).fetchone ()[0 ]
159
+ self .assertEqual (count , 3 )
160
+ changes = sql (self .con2 , "delete from t" ).rowcount
161
+ self .assertEqual (changes , 3 )
162
+ self .con2 .commit ()
163
+
164
+ # Back in original connection, create 2 new users.
165
+ sql (self .con1 , "insert into t values (?)" , "u4" )
166
+ sql (self .con1 , "insert into t values (?)" , "u5" )
167
+
168
+ # The second connection cannot see uncommitted changes.
169
+ count = sql (self .con2 , "select count(*) from t" ).fetchone ()[0 ]
170
+ self .assertEqual (count , 0 )
171
+
172
+ # First connection can see its own changes.
173
+ count = sql (self .con1 , "select count(*) from t" ).fetchone ()[0 ]
174
+ self .assertEqual (count , 2 )
175
+
176
+ # The second connection can now see the changes.
177
+ self .con1 .commit ()
178
+ count = sql (self .con2 , "select count(*) from t" ).fetchone ()[0 ]
179
+ self .assertEqual (count , 2 )
180
+
142
181
143
182
class RollbackTests (unittest .TestCase ):
144
183
"""bpo-44092: sqlite3 now leaves it to SQLite to resolve rollback issues"""
0 commit comments