Resulta que el problema es bastante incómodo. En resumen, la mayoría de las variedades y especies en tipos de datos de cadena MySQL asigne a un solo tipo de datos en la interfaz de MySQL con un indicador BINARIO adicional.
Por lo tanto, VARCHAR
de MySQL , VARBINARY
, y un mapa literal de cadena al mismo MySQLdb.constants.FIELD_TYPE.VAR_STRING
escriba definiciones de tipo de columna, pero con un MySQLdb.constants.FLAG.BINARY
adicional marcar cuando el tipo es VARBINARY
o una cadena cotejada con un *_bin
colación.
Aunque hay un MySQLdb.constants.FIELD_TYPE.VARCHAR
tipo, no pude averiguar cuándo se usa. Como dije, MySQL VARCHAR
las columnas se asignan a FIELD_TYPE.VAR_STRING
.
La solución se vuelve bastante frágil si su aplicación usa cadenas binarias verdaderas (por ejemplo, almacena imágenes y las obtiene con la misma conexión que el texto), ya que asume la decodificación de todas las cadenas binarias a unicode. Sin embargo, funciona.
Como documentos oficiales estados:
En la práctica, el verdadero dolor en el culo podría ser el proceso de construir su propio diccionario de convertidores. Pero puede importar el predeterminado desde MySQLdb.converters.conversions
y parchearlo, o incluso parchearlo en una instancia de Connection. El truco consiste en eliminar un convertidor especial para FLAG.BINARY
marcar y agregar un decodificador para todos los casos. Si especifica explícitamente un charset
parámetro para MySQLdb.connect
, fuerza use_unicode=1
parámetro, que agrega el decodificador por ti, pero puedes hacerlo tú mismo:
>>> 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',)
Probablemente necesites hacer el mismo truco para FIELD_TYPE.STRING
si es necesario.
Otra solución es pasar use_unicode=0
explícito a MySQLdb.connect
y hacer todas las decodificaciones en su código, pero no lo haría.
Espero que esto pueda ser útil para alguien.