@@ -317,6 +317,75 @@ def test_cursor_iteration():
317317 except Exception as e :
318318 return jsonify ({"error" : str (e )}), 500
319319
320+ @app .route ("/test/executemany-returning" )
321+ def test_executemany_returning ():
322+ """Test executemany with returning=True.
323+
324+ Tests whether the instrumentation correctly handles executemany with returning=True.
325+ """
326+ try :
327+ with psycopg .connect (get_conn_string ()) as conn , conn .cursor () as cur :
328+ # Create temp table
329+ cur .execute ("CREATE TEMP TABLE batch_test (id SERIAL, name TEXT)" )
330+
331+ # Use executemany with returning
332+ params = [("Batch User 1" ,), ("Batch User 2" ,), ("Batch User 3" ,)]
333+ cur .executemany (
334+ "INSERT INTO batch_test (name) VALUES (%s) RETURNING id, name" ,
335+ params ,
336+ returning = True
337+ )
338+
339+ # Fetch results from each batch
340+ results = []
341+ for result in cur .results ():
342+ row = result .fetchone ()
343+ if row :
344+ results .append ({"id" : row [0 ], "name" : row [1 ]})
345+
346+ conn .commit ()
347+
348+ return jsonify ({
349+ "count" : len (results ),
350+ "data" : results
351+ })
352+ except Exception as e :
353+ return jsonify ({"error" : str (e )}), 500
354+
355+ # ============================================================================
356+ # BUG HUNTING TEST ENDPOINTS
357+ # These endpoints expose confirmed bugs in the instrumentation
358+ # ============================================================================
359+
360+ @app .route ("/test/cursor-scroll" )
361+ def test_cursor_scroll ():
362+ """Test cursor.scroll() method.
363+
364+ BUG: The MockCursor and InstrumentedCursor classes don't implement
365+ the scroll() method. In replay mode, scroll() causes "no result available"
366+ error on subsequent fetchone() calls.
367+ """
368+ try :
369+ with psycopg .connect (get_conn_string ()) as conn , conn .cursor () as cur :
370+ cur .execute ("SELECT id, name FROM users ORDER BY id" )
371+
372+ # Fetch first row
373+ first = cur .fetchone ()
374+
375+ # Scroll back to start
376+ cur .scroll (0 , mode = 'absolute' )
377+
378+ # Fetch first row again
379+ first_again = cur .fetchone ()
380+
381+ return jsonify ({
382+ "first" : {"id" : first [0 ], "name" : first [1 ]} if first else None ,
383+ "first_again" : {"id" : first_again [0 ], "name" : first_again [1 ]} if first_again else None ,
384+ "match" : first == first_again
385+ })
386+ except Exception as e :
387+ return jsonify ({"error" : str (e )}), 500
388+
320389
321390if __name__ == "__main__" :
322391 sdk .mark_app_as_ready ()
0 commit comments