Okazuje się, że problem jest dość niezręczny. Krótko mówiąc, większość odmian i gatunków w ciągowych typach danych MySQL mapowanie na pojedynczy typ danych w interfejsie MySQL z dodatkową flagą BINARY.
Tak więc VARCHAR
MySQL , VARBINARY
i mapowanie literału ciągu na ten sam MySQLdb.constants.FIELD_TYPE.VAR_STRING
wpisać definicje typów kolumn, ale z dodatkowym MySQLdb.constants.FLAG.BINARY
flaga, gdy typem jest VARBINARY
lub ciąg połączony z *_bin
zestawienie.
Mimo że istnieje MySQLdb.constants.FIELD_TYPE.VARCHAR
typ, nie udało mi się dowiedzieć, kiedy jest używany. Jak powiedziałem, MySQL VARCHAR
kolumny są mapowane na FIELD_TYPE.VAR_STRING
.
Rozwiązanie staje się raczej kruche, jeśli aplikacja używa prawdziwych ciągów binarnych (na przykład przechowujesz obrazy i pobierasz je za pomocą tego samego połączenia co tekst), ponieważ zakłada dekodowanie wszystkich ciągów binarnych do Unicode. Chociaż to działa.
Jako oficjalna dokumentacja stany:
W praktyce prawdziwym utrapieniem może być proces konstruowania własnego słownika konwerterów. Ale możesz zaimportować domyślny z MySQLdb.converters.conversions
i załataj go, a nawet załataj na instancji połączenia. Sztuką jest usunięcie specjalnego konwertera dla pliku FLAG.BINARY
flag i dodaj dekoder dla wszystkich przypadków. Jeśli jawnie określisz charset
parametr dla MySQLdb.connect
, wymusza use_unicode=1
parametr, który dodaje dekoder za Ciebie, ale możesz to zrobić sam:
>>> 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',)
Prawdopodobnie będziesz musiał wykonać ten sam hack dla FIELD_TYPE.STRING
w razie potrzeby.
Innym rozwiązaniem jest przekazanie jawnego use_unicode=0
do MySQLdb.connect
i dokonaj wszystkich dekodowań w swoim kodzie, ale ja bym tego nie robił.
Mam nadzieję, że może się to komuś przydać.