31
31
from . import errors
32
32
from .abstracts import MySQLCursorAbstract , NAMED_TUPLE_CACHE
33
33
from .catch23 import PY2
34
+ from .constants import ServerFlag
34
35
35
36
SQL_COMMENT = r"\/\*.*?\*\/"
36
37
RE_SQL_COMMENT = re .compile (
60
61
61
62
ERR_NO_RESULT_TO_FETCH = "No result set to fetch from"
62
63
64
+ MAX_RESULTS = 4294967295
63
65
64
66
class _ParamSubstitutor (object ):
65
67
"""
@@ -1080,6 +1082,36 @@ def __init__(self, connection=None):
1080
1082
self ._prepared = None
1081
1083
self ._binary = True
1082
1084
self ._have_result = None
1085
+ self ._last_row_sent = False
1086
+ self ._cursor_exists = False
1087
+
1088
+ def reset (self , free = True ):
1089
+ if self ._prepared :
1090
+ try :
1091
+ self ._connection .cmd_stmt_close (self ._prepared ['statement_id' ])
1092
+ except errors .Error :
1093
+ # We tried to deallocate, but it's OK when we fail.
1094
+ pass
1095
+ self ._prepared = None
1096
+ self ._last_row_sent = False
1097
+ self ._cursor_exists = False
1098
+
1099
+ def _handle_noresultset (self , res ):
1100
+ self ._handle_server_status (res .get ('status_flag' ,
1101
+ res .get ('server_status' , 0 )))
1102
+ super (MySQLCursorPrepared , self )._handle_noresultset (res )
1103
+
1104
+ def _handle_server_status (self , flags ):
1105
+ """Check for SERVER_STATUS_CURSOR_EXISTS and
1106
+ SERVER_STATUS_LAST_ROW_SENT flags set by the server.
1107
+ """
1108
+ self ._cursor_exists = flags & ServerFlag .STATUS_CURSOR_EXISTS != 0
1109
+ self ._last_row_sent = flags & ServerFlag .STATUS_LAST_ROW_SENT != 0
1110
+
1111
+ def _handle_eof (self , eof ):
1112
+ self ._handle_server_status (eof .get ('status_flag' ,
1113
+ eof .get ('server_status' , 0 )))
1114
+ super (MySQLCursorPrepared , self )._handle_eof (eof )
1083
1115
1084
1116
def callproc (self , * args , ** kwargs ):
1085
1117
"""Calls a stored procedue
@@ -1094,13 +1126,7 @@ def close(self):
1094
1126
This method will try to deallocate the prepared statement and close
1095
1127
the cursor.
1096
1128
"""
1097
- if self ._prepared :
1098
- try :
1099
- self ._connection .cmd_stmt_close (self ._prepared ['statement_id' ])
1100
- except errors .Error :
1101
- # We tried to deallocate, but it's OK when we fail.
1102
- pass
1103
- self ._prepared = None
1129
+ self .reset ()
1104
1130
super (MySQLCursorPrepared , self ).close ()
1105
1131
1106
1132
def _row_to_python (self , rowdata , desc = None ):
@@ -1122,6 +1148,11 @@ def _handle_result(self, res):
1122
1148
self ._connection .unread_result = True
1123
1149
self ._have_result = True
1124
1150
1151
+ if 'status_flag' in res [2 ]:
1152
+ self ._handle_server_status (res [2 ]['status_flag' ])
1153
+ elif 'server_status' in res [2 ]:
1154
+ self ._handle_server_status (res [2 ]['server_status' ])
1155
+
1125
1156
def execute (self , operation , params = (), multi = False ): # multi is unused
1126
1157
"""Prepare and execute a MySQL Prepared Statement
1127
1158
@@ -1199,6 +1230,8 @@ def fetchone(self):
1199
1230
1200
1231
Returns a tuple or None.
1201
1232
"""
1233
+ if self ._cursor_exists :
1234
+ self ._connection .cmd_stmt_fetch (self ._prepared ['statement_id' ])
1202
1235
return self ._fetch_row () or None
1203
1236
1204
1237
def fetchmany (self , size = None ):
@@ -1214,10 +1247,18 @@ def fetchmany(self, size=None):
1214
1247
def fetchall (self ):
1215
1248
if not self ._have_unread_result ():
1216
1249
raise errors .InterfaceError ("No result set to fetch from." )
1217
- (rows , eof ) = self ._connection .get_rows (
1218
- binary = self ._binary , columns = self .description )
1250
+ rows = []
1251
+ if self ._nextrow [0 ]:
1252
+ rows .append (self ._nextrow [0 ])
1253
+ while self ._have_unread_result ():
1254
+ if self ._cursor_exists :
1255
+ self ._connection .cmd_stmt_fetch (
1256
+ self ._prepared ['statement_id' ], MAX_RESULTS )
1257
+ (tmp , eof ) = self ._connection .get_rows (
1258
+ binary = self ._binary , columns = self .description )
1259
+ rows .extend (tmp )
1260
+ self ._handle_eof (eof )
1219
1261
self ._rowcount = len (rows )
1220
- self ._handle_eof (eof )
1221
1262
return rows
1222
1263
1223
1264
0 commit comments