@@ -211,13 +211,17 @@ def __init__(self, connection: Any, instrumentation: Psycopg2Instrumentation, sd
211211 object .__setattr__ (self , "_connection" , connection )
212212 object .__setattr__ (self , "_instrumentation" , instrumentation )
213213 object .__setattr__ (self , "_sdk" , sdk )
214+ # Preserve the connection's default cursor_factory (set at connect() time)
215+ object .__setattr__ (self , "_default_cursor_factory" , getattr (connection , "cursor_factory" , None ))
214216
215217 def cursor (self , name : str | None = None , cursor_factory : Any = None , * args : Any , ** kwargs : Any ) -> Any :
216218 """Intercept cursor creation to wrap user-provided cursor_factory."""
217- # Create instrumented cursor factory (wrapping user's factory if provided)
219+ # Use cursor_factory from cursor() call, or fall back to connection's default
220+ base_factory = cursor_factory if cursor_factory is not None else self ._default_cursor_factory
221+ # Create instrumented cursor factory (wrapping the base factory)
218222 wrapped_factory = self ._instrumentation ._create_cursor_factory (
219223 self ._sdk ,
220- cursor_factory , # This becomes the base class (None uses default)
224+ base_factory ,
221225 )
222226 return self ._connection .cursor (* args , name = name , cursor_factory = wrapped_factory , ** kwargs )
223227
@@ -606,11 +610,12 @@ def _traced_executemany(
606610
607611 # For all other queries (pre-app-start OR within a request trace), get mock
608612 # Wrap in {"_batch": ...} to match the recording format
613+ # Normalize to list to match RECORD mode and avoid iterator/serialization issues
609614 is_pre_app_start = not sdk .app_ready
610615 mock_result = self ._try_get_mock (
611616 sdk ,
612617 query ,
613- {"_batch" : params_list },
618+ {"_batch" : list ( params_list ) },
614619 trace_id ,
615620 span_id ,
616621 parent_span_id ,
@@ -642,9 +647,11 @@ def _traced_executemany(
642647
643648 # RECORD mode: Execute real query and record span
644649 error = None
650+ # Convert to list BEFORE executing to avoid iterator exhaustion
651+ params_as_list = list (params_list )
645652
646653 try :
647- result = original_executemany (query , params_list )
654+ result = original_executemany (query , params_as_list )
648655 return result
649656 except Exception as e :
650657 error = e
@@ -656,7 +663,7 @@ def _traced_executemany(
656663 span ,
657664 cursor ,
658665 query ,
659- {"_batch" : list ( params_list ) },
666+ {"_batch" : params_as_list },
660667 error ,
661668 )
662669 finally :
0 commit comments