Skip to content

Commit ecd8a66

Browse files
committed
Move convertor and encoding selection out of row reading loop
This reduces amount of work done in row reading loop to minimum
1 parent 65292f5 commit ecd8a66

2 files changed

Lines changed: 38 additions & 26 deletions

File tree

pymysql/connections.py

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@
3939
from .cursors import Cursor
4040
from .constants import CLIENT, COMMAND, FIELD_TYPE, SERVER_STATUS
4141
from .util import byte2int, int2byte
42-
from .converters import escape_item, encoders, decoders, escape_string
42+
from .converters import (
43+
escape_item, encoders, decoders, escape_string, through)
4344
from .err import (
4445
raise_mysql_exception, Warning, Error,
4546
InterfaceError, DataError, DatabaseError, OperationalError,
@@ -1225,23 +1226,12 @@ def _read_rowdata_packet(self):
12251226
self.rows = tuple(rows)
12261227

12271228
def _read_row_from_packet(self, packet):
1228-
use_unicode = self.connection.use_unicode
12291229
row = []
1230-
for field in self.fields:
1230+
for encoding, converter in self.converters:
12311231
data = packet.read_length_coded_string()
12321232
if data is not None:
1233-
field_type = field.type_code
1234-
if use_unicode:
1235-
if field_type in TEXT_TYPES:
1236-
charset = charset_by_id(field.charsetnr)
1237-
if use_unicode and not charset.is_binary:
1238-
# TEXTs with charset=binary means BINARY types.
1239-
data = data.decode(charset.encoding)
1240-
else:
1241-
data = data.decode()
1242-
1243-
converter = self.connection.decoders.get(field_type)
1244-
if DEBUG: print("DEBUG: field={}, converter={}".format(field, converter))
1233+
if encoding is not None:
1234+
data = data.decode(encoding)
12451235
if DEBUG: print("DEBUG: DATA = ", data)
12461236
if converter is not None:
12471237
data = converter(data)
@@ -1251,11 +1241,31 @@ def _read_row_from_packet(self, packet):
12511241
def _get_descriptions(self):
12521242
"""Read a column descriptor packet for each column in the result."""
12531243
self.fields = []
1244+
self.converters = []
1245+
use_unicode = self.connection.use_unicode
12541246
description = []
12551247
for i in range_type(self.field_count):
12561248
field = self.connection._read_packet(FieldDescriptorPacket)
12571249
self.fields.append(field)
12581250
description.append(field.description())
1251+
field_type = field.type_code
1252+
if use_unicode:
1253+
if field_type in TEXT_TYPES:
1254+
charset = charset_by_id(field.charsetnr)
1255+
if charset.is_binary:
1256+
encoding = None
1257+
else:
1258+
# TEXTs with charset=binary means BINARY types.
1259+
encoding = charset.encoding
1260+
else:
1261+
encoding = 'ascii'
1262+
else:
1263+
encoding = None
1264+
converter = self.connection.decoders.get(field_type)
1265+
if converter is through:
1266+
converter = None
1267+
if DEBUG: print("DEBUG: field={}, converter={}".format(field, converter))
1268+
self.converters.append((encoding, converter))
12591269

12601270
eof_packet = self.connection._read_packet()
12611271
assert eof_packet.is_eof_packet(), 'Protocol error, expecting EOF'

pymysql/converters.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -254,13 +254,19 @@ def convert_mysql_timestamp(timestamp):
254254
def convert_set(s):
255255
return set(s.split(","))
256256

257-
def convert_bit(b):
258-
#b = "\x00" * (8 - len(b)) + b # pad w/ zeroes
259-
#return struct.unpack(">Q", b)[0]
260-
#
261-
# the snippet above is right, but MySQLdb doesn't process bits,
262-
# so we shouldn't either
263-
return b
257+
258+
def through(x):
259+
return x
260+
261+
262+
#def convert_bit(b):
263+
# b = "\x00" * (8 - len(b)) + b # pad w/ zeroes
264+
# return struct.unpack(">Q", b)[0]
265+
#
266+
# the snippet above is right, but MySQLdb doesn't process bits,
267+
# so we shouldn't either
268+
convert_bit = through
269+
264270

265271
def convert_characters(connection, field, data):
266272
field_charset = charset_by_id(field.charsetnr).name
@@ -297,10 +303,6 @@ def convert_characters(connection, field, data):
297303
Decimal: str,
298304
}
299305

300-
301-
def through(x):
302-
return x
303-
304306
if not PY2 or JYTHON or IRONPYTHON:
305307
encoders[bytes] = escape_bytes
306308

0 commit comments

Comments
 (0)