Skip to content

Commit ab3906d

Browse files
author
Bartek Ogryczak
committed
Making Column attribiutes into regular object attributes instead of a dictionary.
This makes getting the attribute about 20 times faster. Rationale behind this is the fact that 15% of time spent on creating and using RowsEvent was spent on Column.__getattr__. There is more to be optimized, but this one was a low hanging fruit.
1 parent 0329902 commit ab3906d

File tree

1 file changed

+33
-36
lines changed

1 file changed

+33
-36
lines changed

pymysqlreplication/column.py

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,76 +10,75 @@ class Column(object):
1010
"""
1111

1212
def __init__(self, *args, **kwargs):
13-
self.data = {}
1413
if len(args) == 3:
1514
self.__parse_column_definition(*args)
1615
else:
17-
self.data = kwargs
16+
self.__dict__.update(kwargs)
1817

1918
def __parse_column_definition(self, column_type, column_schema, packet):
20-
self.data["type"] = column_type
21-
self.data["name"] = column_schema["COLUMN_NAME"]
22-
self.data["collation_name"] = column_schema["COLLATION_NAME"]
23-
self.data["character_set_name"] = column_schema["CHARACTER_SET_NAME"]
24-
self.data["comment"] = column_schema["COLUMN_COMMENT"]
25-
self.data["unsigned"] = False
26-
self.data["type_is_bool"] = False
19+
self.type = column_type
20+
self.name = column_schema["COLUMN_NAME"]
21+
self.collation_name = column_schema["COLLATION_NAME"]
22+
self.character_set_name = column_schema["CHARACTER_SET_NAME"]
23+
self.comment = column_schema["COLUMN_COMMENT"]
24+
self.unsigned = False
25+
self.type_is_bool = False
2726
if column_schema["COLUMN_KEY"] == "PRI":
28-
self.data["is_primary"] = True
27+
self.is_primary = True
2928
else:
30-
self.data["is_primary"] = False
29+
self.is_primary = False
3130

3231
if column_schema["COLUMN_TYPE"].find("unsigned") != -1:
33-
self.data["unsigned"] = True
32+
self.unsigned = True
3433
if self.type == FIELD_TYPE.VAR_STRING or \
3534
self.type == FIELD_TYPE.STRING:
3635
self.__read_string_metadata(packet, column_schema)
3736
elif self.type == FIELD_TYPE.VARCHAR:
38-
self.data["max_length"] = struct.unpack('<H', packet.read(2))[0]
37+
self.max_length = struct.unpack('<H', packet.read(2))[0]
3938
elif self.type == FIELD_TYPE.BLOB:
40-
self.data["length_size"] = packet.read_uint8()
39+
self.length_size = packet.read_uint8()
4140
elif self.type == FIELD_TYPE.GEOMETRY:
42-
self.data["length_size"] = packet.read_uint8()
41+
self.length_size = packet.read_uint8()
4342
elif self.type == FIELD_TYPE.NEWDECIMAL:
44-
self.data["precision"] = packet.read_uint8()
45-
self.data["decimals"] = packet.read_uint8()
43+
self.precision = packet.read_uint8()
44+
self.decimals = packet.read_uint8()
4645
elif self.type == FIELD_TYPE.DOUBLE:
47-
self.data["size"] = packet.read_uint8()
46+
self.size = packet.read_uint8()
4847
elif self.type == FIELD_TYPE.FLOAT:
49-
self.data["size"] = packet.read_uint8()
48+
self.size = packet.read_uint8()
5049
elif self.type == FIELD_TYPE.BIT:
5150
bits = packet.read_uint8()
5251
bytes = packet.read_uint8()
53-
self.data["bits"] = (bytes * 8) + bits
54-
self.data["bytes"] = int((self.bits + 7) / 8)
52+
self.bits = (bytes * 8) + bits
53+
self.bytes = int((self.bits + 7) / 8)
5554
elif self.type == FIELD_TYPE.TIMESTAMP2:
56-
self.data["fsp"] = packet.read_uint8()
55+
self.fsp = packet.read_uint8()
5756
elif self.type == FIELD_TYPE.DATETIME2:
58-
self.data["fsp"] = packet.read_uint8()
57+
self.fsp = packet.read_uint8()
5958
elif self.type == FIELD_TYPE.TIME2:
60-
self.data["fsp"] = packet.read_uint8()
59+
self.fsp = packet.read_uint8()
6160
elif self.type == FIELD_TYPE.TINY and \
6261
column_schema["COLUMN_TYPE"] == "tinyint(1)":
63-
self.data["type_is_bool"] = True
62+
self.type_is_bool = True
6463

6564
def __read_string_metadata(self, packet, column_schema):
6665
metadata = (packet.read_uint8() << 8) + packet.read_uint8()
6766
real_type = metadata >> 8
6867
if real_type == FIELD_TYPE.SET or real_type == FIELD_TYPE.ENUM:
69-
self.data["type"] = real_type
70-
self.data["size"] = metadata & 0x00ff
68+
self.type = real_type
69+
self.size = metadata & 0x00ff
7170
self.__read_enum_metadata(column_schema)
7271
else:
73-
self.data["max_length"] = (((metadata >> 4) & 0x300) ^ 0x300) \
72+
self.max_length = (((metadata >> 4) & 0x300) ^ 0x300) \
7473
+ (metadata & 0x00ff)
7574

7675
def __read_enum_metadata(self, column_schema):
7776
enums = column_schema["COLUMN_TYPE"]
7877
if self.type == FIELD_TYPE.ENUM:
79-
self.data["enum_values"] = enums.replace('enum(', '')\
78+
self.enum_values = enums.replace('enum(', '')\
8079
.replace(')', '').replace('\'', '').split(',')
8180
else:
82-
self.data["set_values"] = enums.replace('set(', '')\
81+
self.set_values = enums.replace('set(', '')\
8382
.replace(')', '').replace('\'', '').split(',')
8483

8584
def __eq__(self, other):
@@ -89,10 +88,8 @@ def __ne__(self, other):
8988
return not self.__eq__(other)
9089

9190
def serializable_data(self):
92-
return self.data
91+
return dict((k, v) for (k, v) in self.__dict__.items() if not k.startswith('_'))
9392

94-
def __getattr__(self, item):
95-
try:
96-
return self.data[item]
97-
except KeyError:
98-
raise AttributeError("{0} not found".format(item))
93+
@property
94+
def data(self):
95+
return self.serializable_data()

0 commit comments

Comments
 (0)