Det viser sig, at problemet er ret akavet. Kort sagt, de fleste varianter og arter i MySQL-strengdatatyper a> map til en enkelt datatype i MySQL's grænseflade med et ekstra BINÆRT flag.
Således MySQL's VARCHAR
, VARBINARY
, og en bogstavlig streng mappe til den samme MySQLdb.constants.FIELD_TYPE.VAR_STRING
indtast kolonnetypedefinitioner, men med en ekstra MySQLdb.constants.FLAG.BINARY
flag, når typen er VARBINARY
eller en streng sammensat med en *_bin
sortering.
Selvom der er en MySQLdb.constants.FIELD_TYPE.VARCHAR
type, kunne jeg ikke finde ud af, hvornår den er brugt. Som jeg sagde, MySQL VARCHAR
kolonner er knyttet til FIELD_TYPE.VAR_STRING
.
Løsningen bliver ret skrøbelig, hvis din applikation bruger ægte binære strenge (f.eks. gemmer du billeder og henter dem med samme forbindelse som tekst), da den forudsætter afkodning af alle binære strenge til unicode. Selvom det virker.
Som officielle dokumenter siger:
I praksis kan virkelig smerte i røven være processen med at konstruere din egen konverterordbog. Men du kan importere standarden fra MySQLdb.converters.conversions
og patch det, eller endda patch det på en instans af forbindelsen. Tricket er at fjerne en speciel konverter til en FLAG.BINARY
flag og tilføje en dekoder til alle tilfælde. Hvis du udtrykkeligt angiver et charset
parameter for MySQLdb.connect
, tvinger det use_unicode=1
parameter, som tilføjer dekoderen for dig, men du kan gøre det selv:
>>> 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',)
Du skal muligvis lave det samme hack til FIELD_TYPE.STRING
om nødvendigt.
En anden løsning er at sende eksplicitte use_unicode=0
til MySQLdb.connect
og lav alle afkodninger i din kode, men det ville jeg ikke.
Håber, dette kan være nyttigt for nogen.