77"""
88import sys
99import os
10+ import weakref
1011import warnings
1112import collections
1213
@@ -202,13 +203,19 @@ def _init(self):
202203 """
203204
204205 def __init__ (self , cursor_id ):
206+ self .cursor_id = cursor_id
205207 if self .statement is not None :
206208 self ._output = self .statement ._output
207209 self ._output_io = self .statement ._output_io
208210 self ._output_formats = self .statement ._output_formats or ()
209211 self ._output_attmap = self .statement ._output_attmap
210212
211- self .cursor_id = cursor_id
213+ if self .cursor_id == ID (self ):
214+ addgarbage = self .database .pq .garbage_cursors .append
215+ typio = self .database .typio
216+ self ._del = weakref .ref (
217+ self , lambda x : addgarbage (typio .encode (cursor_id ))
218+ )
212219 self ._quoted_cursor_id = '"' + self .cursor_id .replace ('"' , '""' ) + '"'
213220 self ._pq_cursor_id = self .database .typio .encode (self .cursor_id )
214221 self ._init ()
@@ -221,19 +228,12 @@ def close(self):
221228 self .database .pq .garbage_cursors .append (
222229 self .database .typio .encode (self .cursor_id )
223230 )
224- self .closed = True
225-
226- def __del__ (self ):
227- if not self .closed and ID (self ) == self .cursor_id :
228- self .database .pq .garbage_cursors .append (
229- self .database .typio .encode (self .cursor_id )
230- )
231-
232- def _asynchook (self , * args ):
233- self .database ._receive_async (* args , controller = self )
231+ self .closed = True
232+ if hasattr (self , '_del' ):
233+ del self ._del
234234
235235 def _ins (self , * args ):
236- return xact .Instruction (* args , asynchook = self ._asynchook )
236+ return xact .Instruction (* args , asynchook = self .database . _receive_async )
237237
238238 def _pq_xp_describe (self ):
239239 return (element .DescribePortal (self ._pq_cursor_id ),)
@@ -435,6 +435,9 @@ def _init(self):
435435 elif x .type is element .Complete .type :
436436 self ._complete_message = x
437437 self .database ._pq_complete ()
438+ # If this was a select/copy cursor,
439+ # the data messages would have caused an earlier
440+ # return.
438441 self ._xact = None
439442 return
440443 elif x .type is expect :
@@ -468,7 +471,6 @@ def __next__(self):
468471 if not x .completed :
469472 # Transaction has been cleaned out of completed? iterator is done.
470473 self ._xact = None
471- self .closed = True
472474 raise StopIteration
473475
474476 chunk = x .completed [0 ][1 ]
@@ -526,7 +528,6 @@ def __next__(self):
526528 self .database ._pq_push (self ._xact , self )
527529 else :
528530 # it's done.
529- self .close ()
530531 self ._xact = None
531532 if not chunk :
532533 raise StopIteration
@@ -706,8 +707,13 @@ def __init__(self, database, statement_id, string):
706707 self ._pq_statement_id = None
707708 self .closed = None
708709
709- def _receive_async (self , * args ):
710- return self .database ._receive_async (* args , controller = self )
710+ if not statement_id :
711+ addgarbage = database .pq .garbage_statements .append
712+ typio = database .typio
713+ sid = self .statement_id
714+ self ._del = weakref .ref (
715+ self , lambda x : addgarbage (typio .encode (sid ))
716+ )
711717
712718 def __repr__ (self ):
713719 return '<{mod}.{name}[{ci}] {state}>' .format (
@@ -837,18 +843,11 @@ def sql_parameter_types(self):
837843 ]
838844
839845 def close (self ):
840- if not ( self .closed is True ) :
846+ if self .closed is False :
841847 self .database .pq .garbage_statements .append (self ._pq_statement_id )
842848 self .closed = True
843-
844- def __del__ (self ):
845- # Only close statements that have generated IDs as the ones
846- # with explicitly created
847- if not self .closed and ID (self ) == self .statement_id :
848- # Always close CPSs as the way the statement_id is generated
849- # might cause a conflict if Python were to reuse the previously
850- # used id()[it can and has happened]. - jwp 2007
851- self .close ()
849+ if hasattr (self , '_del' ):
850+ del self ._del
852851
853852 def _init (self ):
854853 """
@@ -873,7 +872,7 @@ def _init(self):
873872 element .SynchronizeMessage ,
874873 )
875874 )
876- self ._xact = xact .Instruction (cmd , asynchook = self ._receive_async )
875+ self ._xact = xact .Instruction (cmd , asynchook = self .database . _receive_async )
877876 self .database ._pq_push (self ._xact , self )
878877
879878 def _fini (self ):
@@ -886,7 +885,7 @@ def _fini(self):
886885 if self ._xact is self .database .pq .xact :
887886 try :
888887 self .database ._pq_complete ()
889- except :
888+ except Exception :
890889 self .closed = True
891890 raise
892891
@@ -997,7 +996,7 @@ def first(self, *parameters):
997996 len (self ._input ), len (parameters )
998997 ))
999998 # Parameters? Build em'.
1000- c = self .database
999+ db = self .database
10011000
10021001 if self ._input_io :
10031002 params = pg_typio .process_tuple (
@@ -1019,10 +1018,10 @@ def first(self, *parameters):
10191018 element .Execute (b'' , 0xFFFFFFFF ),
10201019 element .SynchronizeMessage
10211020 ),
1022- asynchook = self ._receive_async
1021+ asynchook = db ._receive_async
10231022 )
1024- c ._pq_push (x , self )
1025- c ._pq_complete ()
1023+ db ._pq_push (x , self )
1024+ db ._pq_complete ()
10261025
10271026 if self ._output_io :
10281027 ##
@@ -1078,7 +1077,7 @@ def _copy_data_in(self,
10781077 element .Execute (b'' , 1 ),
10791078 element .SynchronizeMessage ,
10801079 ),
1081- asynchook = self ._receive_async
1080+ asynchook = self .database . _receive_async
10821081 )
10831082 self .database ._pq_push (x , self )
10841083
@@ -1153,7 +1152,7 @@ def _load_bulk_tuples(self, tupleseq, tps = None):
11531152 last = element .SynchronizeMessage
11541153 xm .append (last )
11551154 self .database ._pq_push (
1156- xact .Instruction (xm , asynchook = self ._receive_async ),
1155+ xact .Instruction (xm , asynchook = self .database . _receive_async ),
11571156 self
11581157 )
11591158 self .database ._pq_complete ()
@@ -2119,7 +2118,7 @@ def _error_lookup(self, om : element.Error,) -> pg_exc.Error:
21192118 return err
21202119
21212120 def _receive_async (self , msg , controller = None ):
2122- c = controller or self
2121+ c = controller or getattr ( self , '_controller' , self )
21232122 if msg .type is element .ShowOption .type :
21242123 if msg .name == b'client_encoding' :
21252124 self .typio .set_encoding (msg .value .decode ('ascii' ))
0 commit comments