@@ -726,7 +726,6 @@ def __del__(self):
726
726
def autocommit (self , value ):
727
727
self .autocommit_mode = bool (value )
728
728
current = self .get_autocommit ()
729
- self .next_packet = 1
730
729
if value != current :
731
730
self ._send_autocommit_mode ()
732
731
@@ -816,15 +815,13 @@ def query(self, sql, unbuffered=False):
816
815
"You may not close previous cursor." )
817
816
# if DEBUG:
818
817
# print("DEBUG: sending query:", sql)
819
- self .next_packet = 1
820
818
if isinstance (sql , text_type ) and not (JYTHON or IRONPYTHON ):
821
819
if PY2 :
822
820
sql = sql .encode (self .encoding )
823
821
else :
824
822
sql = sql .encode (self .encoding , 'surrogateescape' )
825
823
self ._execute_command (COMMAND .COM_QUERY , sql )
826
824
self ._affected_rows = self ._read_query_result (unbuffered = unbuffered )
827
- self .next_packet = 1
828
825
return self ._affected_rows
829
826
830
827
def next_result (self , unbuffered = False ):
@@ -892,7 +889,7 @@ def connect(self, sock=None):
892
889
sock .setsockopt (socket .SOL_SOCKET , socket .SO_KEEPALIVE , 1 )
893
890
self .socket = sock
894
891
self ._rfile = _makefile (sock , 'rb' )
895
- self .next_packet = 0
892
+ self ._next_seq_id = 0
896
893
897
894
self ._get_server_information ()
898
895
self ._request_authentication ()
@@ -933,16 +930,16 @@ def connect(self, sock=None):
933
930
# So just reraise it.
934
931
raise
935
932
936
- def write_packet (self , data ):
933
+ def write_packet (self , payload ):
937
934
"""Writes an entire "mysql packet" in its entirety to the network
938
- addings its length and sequence number. Intended for use by plugins
939
- only.
935
+ addings its length and sequence number.
940
936
"""
941
- data = pack_int24 (len (data )) + int2byte (self .next_packet ) + data
937
+ # Internal note: when you build packet manualy and calls _write_bytes()
938
+ # directly, you should set self._next_seq_id properly.
939
+ data = pack_int24 (len (payload )) + int2byte (self ._next_seq_id ) + payload
942
940
if DEBUG : dump_packet (data )
943
-
944
941
self ._write_bytes (data )
945
- self .next_packet = (self .next_packet + 1 ) % 256
942
+ self ._next_seq_id = (self ._next_seq_id + 1 ) % 256
946
943
947
944
def _read_packet (self , packet_type = MysqlPacket ):
948
945
"""Read an entire "mysql packet" in its entirety from the network
@@ -952,8 +949,14 @@ def _read_packet(self, packet_type=MysqlPacket):
952
949
while True :
953
950
packet_header = self ._read_bytes (4 )
954
951
if DEBUG : dump_packet (packet_header )
952
+
955
953
btrl , btrh , packet_number = struct .unpack ('<HBB' , packet_header )
956
954
bytes_to_read = btrl + (btrh << 16 )
955
+ if packet_number != self ._next_seq_id :
956
+ raise err .InternalError ("Packet sequence number wrong - got %d expected %d" %
957
+ (packet_number , self ._next_seq_id ))
958
+ self ._next_seq_id = (self ._next_seq_id + 1 ) % 256
959
+
957
960
recv_data = self ._read_bytes (bytes_to_read )
958
961
if DEBUG : dump_packet (recv_data )
959
962
buff += recv_data
@@ -962,13 +965,7 @@ def _read_packet(self, packet_type=MysqlPacket):
962
965
continue
963
966
if bytes_to_read < MAX_PACKET_LEN :
964
967
break
965
- if packet_number != self .next_packet :
966
- pass
967
- #TODO: check sequence id
968
- #raise err.InternalError("Packet sequence number wrong - got %d expected %d" %
969
- # (packet_number, self.next_packet))
970
968
971
- self .next_packet = (packet_number + 1 ) % 256
972
969
packet = packet_type (buff , self .encoding )
973
970
packet .check_error ()
974
971
return packet
@@ -1027,33 +1024,32 @@ def _execute_command(self, command, sql):
1027
1024
if self ._result is not None and self ._result .unbuffered_active :
1028
1025
warnings .warn ("Previous unbuffered result was left incomplete" )
1029
1026
self ._result ._finish_unbuffered_query ()
1027
+ self ._result = None
1030
1028
1031
1029
if isinstance (sql , text_type ):
1032
1030
sql = sql .encode (self .encoding )
1033
1031
1034
- chunk_size = min (self .max_allowed_packet , len (sql ) + 1 ) # +1 is for command
1032
+ # +1 is for command
1033
+ chunk_size = min (self .max_allowed_packet , len (sql ) + 1 )
1035
1034
1035
+ # tiny optimization: build first packet manually instead of
1036
+ # calling self..write_packet()
1036
1037
prelude = struct .pack ('<iB' , chunk_size , command )
1037
- self ._write_bytes (prelude + sql [:chunk_size - 1 ])
1038
- if DEBUG : dump_packet (prelude + sql )
1038
+ packet = prelude + sql [:chunk_size - 1 ]
1039
+ self ._write_bytes (packet )
1040
+ if DEBUG : dump_packet (packet )
1041
+ self ._next_seq_id = 1
1039
1042
1040
- self .next_packet = 1
1041
1043
if chunk_size < self .max_allowed_packet :
1042
1044
return
1043
1045
1044
- seq_id = 1
1045
1046
sql = sql [chunk_size - 1 :]
1046
1047
while True :
1047
1048
chunk_size = min (self .max_allowed_packet , len (sql ))
1048
- prelude = struct .pack ('<i' , chunk_size )[:3 ]
1049
- data = prelude + int2byte (seq_id % 256 ) + sql [:chunk_size ]
1050
- self ._write_bytes (data )
1051
- if DEBUG : dump_packet (data )
1049
+ self .write_packet (sql [:chunk_size ])
1052
1050
sql = sql [chunk_size :]
1053
1051
if not sql and chunk_size < self .max_allowed_packet :
1054
1052
break
1055
- seq_id += 1
1056
- self .next_packet = seq_id % 256
1057
1053
1058
1054
def _request_authentication (self ):
1059
1055
# https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse
@@ -1448,9 +1444,8 @@ def send_data(self):
1448
1444
"""Send data packets from the local file to the server"""
1449
1445
if not self .connection .socket :
1450
1446
raise err .InterfaceError ("(0, '')" )
1447
+ conn = self .connection
1451
1448
1452
- # sequence id is 2 as we already sent a query packet
1453
- seq_id = 2
1454
1449
try :
1455
1450
with open (self .filename , 'rb' ) as open_file :
1456
1451
chunk_size = self .connection .max_allowed_packet
@@ -1460,14 +1455,9 @@ def send_data(self):
1460
1455
chunk = open_file .read (chunk_size )
1461
1456
if not chunk :
1462
1457
break
1463
- packet = struct .pack ('<i' , len (chunk ))[:3 ] + int2byte (seq_id )
1464
- format_str = '!{0}s' .format (len (chunk ))
1465
- packet += struct .pack (format_str , chunk )
1466
- self .connection ._write_bytes (packet )
1467
- seq_id = (seq_id + 1 ) % 256
1458
+ conn .write_packet (chunk )
1468
1459
except IOError :
1469
1460
raise err .OperationalError (1017 , "Can't find file '{0}'" .format (self .filename ))
1470
1461
finally :
1471
1462
# send the empty packet to signify we are done sending data
1472
- packet = struct .pack ('<i' , 0 )[:3 ] + int2byte (seq_id )
1473
- self .connection ._write_bytes (packet )
1463
+ conn .write_packet (b'' )
0 commit comments