Оказва се, че проблемът е доста неудобен. Накратко, повечето варианти и видове в типове данни на MySQL низове карта към един тип данни в интерфейса на MySQL с допълнителен BINARY флаг.
По този начин VARCHAR
на MySQL , VARBINARY
, и низов литерал, преобразуван в същия MySQLdb.constants.FIELD_TYPE.VAR_STRING
въведете дефинициите на тип колона, но с допълнителен MySQLdb.constants.FLAG.BINARY
флаг, когато типът е VARBINARY
или низ, съпоставен с *_bin
съпоставяне.
Въпреки че има MySQLdb.constants.FIELD_TYPE.VARCHAR
тип, не успях да разбера кога се използва. Както казах, MySQL VARCHAR
колоните се съпоставят с FIELD_TYPE.VAR_STRING
.
Решението става доста крехко, ако приложението ви използва истински двоични низове (например съхранявате изображения и ги извличате със същата връзка като текста), тъй като предполага декодиране на всички двоични низове в unicode. Въпреки това работи.
Като официални документи гласи:
На практика истинска болка в задника може да бъде процесът на изграждане на свой собствен речник за конвертори. Но можете да импортирате този по подразбиране от MySQLdb.converters.conversions
и го поправете или дори го поправете на екземпляр на връзката. Номерът е да премахнете специален конвертор за FLAG.BINARY
флаг и добавете декодер за всички случаи. Ако изрично посочите charset
параметър за MySQLdb.connect
, принуждава use_unicode=1
параметър, който добавя декодера вместо вас, но можете да го направите сами:
>>> con = MySQLdb.connect(**params)
>>> con.converter[FIELD_TYPE.VAR_STRING]
[(128, <type 'str'>), (None, <function string_decoder at 0x01FFA130>)]
>>> con.converter[FIELD_TYPE.VAR_STRING] = [(None, con.string_decoder)]
>>> c = con.cursor()
>>> c.execute("SELECT %s COLLATE utf8_bin", u'м')
1L
>>> c.fetchone()
(u'\u043c',)
Може да се наложи да направите същия хак за FIELD_TYPE.STRING
ако е необходимо.
Друго решение е да предадете изрично use_unicode=0
към MySQLdb.connect
и да направя всички декодиране във вашия код, но аз не бих.
Надявам се, това може да е полезно за някого.