Ukazuje se, že problém je poněkud nepříjemný. Stručně řečeno, většina variací a druhů v datových typech řetězců MySQL mapovat na jeden datový typ v rozhraní MySQL s dalším příznakem BINARY.
Tedy VARCHAR
MySQL , VARBINARY
a mapování řetězcového literálu na stejný MySQLdb.constants.FIELD_TYPE.VAR_STRING
zadejte definice typů sloupců, ale mají další MySQLdb.constants.FLAG.BINARY
příznak, když je typ VARBINARY
nebo řetězec porovnaný s *_bin
řazení.
I když existuje MySQLdb.constants.FIELD_TYPE.VARCHAR
typu, nepodařilo se mi zjistit, kdy se používá. Jak jsem řekl, MySQL VARCHAR
sloupce se mapují na FIELD_TYPE.VAR_STRING
.
Řešení se stává poněkud křehkým, pokud vaše aplikace používá skutečné binární řetězce (například ukládáte obrázky a načítáte je se stejným připojením jako text), protože předpokládá dekódování všech binárních řetězců do unicode. I když to funguje.
Jako oficiální dokumenty uvádí:
V praxi může být skutečnou bolestí v zadku proces vytváření vlastního slovníku převodníků. Můžete však importovat výchozí z MySQLdb.converters.conversions
a opravte jej nebo dokonce opravte na instanci Connection. Trik je v odstranění speciálního konvertoru pro FLAG.BINARY
příznak a přidat dekodér pro všechny případy. Pokud explicitně zadáte charset
parametr pro MySQLdb.connect
, vynutí use_unicode=1
parametr, který přidá dekodér za vás, ale můžete to udělat sami:
>>> 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',)
Pravděpodobně budete muset provést stejný hack pro FIELD_TYPE.STRING
v případě potřeby.
Dalším řešením je předat explicitní use_unicode=0
na MySQLdb.connect
a provést všechna dekódování ve vašem kódu, ale to bych neudělal.
Doufám, že to může být pro někoho užitečné.