Si scopre che il problema è piuttosto imbarazzante. In breve, la maggior parte delle varietà e delle specie in tipi di dati di stringhe MySQL mappa a un singolo tipo di dati nell'interfaccia di MySQL con un flag BINARY aggiuntivo.
Pertanto, VARCHAR
di MySQL , VARBINARY
e una mappa letterale stringa allo stesso MySQLdb.constants.FIELD_TYPE.VAR_STRING
digitare le definizioni del tipo di colonna, ma con un ulteriore MySQLdb.constants.FLAG.BINARY
flag quando il tipo è VARBINARY
o una stringa confrontata con un *_bin
confronto.
Anche se esiste un MySQLdb.constants.FIELD_TYPE.VARCHAR
tipo, non sono riuscito a scoprire quando viene utilizzato. Come ho detto, MySQL VARCHAR
colonne mappa a FIELD_TYPE.VAR_STRING
.
La soluzione diventa piuttosto fragile, se la tua applicazione utilizza stringhe binarie vere (ad esempio, memorizzi immagini e le recuperi con la stessa connessione del testo), poiché presuppone la decodifica di tutte le stringhe binarie in unicode. Comunque funziona.
Come documenti ufficiali afferma:
In pratica, il vero dolore nel culo potrebbe essere il processo di costruzione del tuo dizionario di convertitori. Ma puoi importare quello predefinito da MySQLdb.converters.conversions
e patchalo, o addirittura patchalo su un'istanza di Connection. Il trucco è rimuovere un convertitore speciale per un FLAG.BINARY
flag e aggiungi un decoder per tutti i casi. Se specifichi esplicitamente un charset
parametro per MySQLdb.connect
, forza use_unicode=1
parametro, che aggiunge il decoder per te, ma puoi farlo da solo:
>>> 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',)
Probabilmente potresti dover fare lo stesso hack per FIELD_TYPE.STRING
se richiesto.
Un'altra soluzione è passare use_unicode=0
esplicito a MySQLdb.connect
e fare tutte le decodifiche nel tuo codice, ma non lo farei.
Spero che questo possa essere utile a qualcuno.