Ticket #2635: django-mysql5.patch

File django-mysql5.patch, 4.7 KB (added by Andy Dustman <farcepest@…>, 18 years ago)

Patch for improved MySQL support

  • django/db/backends/mysql/base.py

     
    1010except ImportError, e:
    1111    from django.core.exceptions import ImproperlyConfigured
    1212    raise ImproperlyConfigured, "Error loading MySQLdb module: %s" % e
     13if Database.version_info < (1,2,1,'final',1):
     14    raise ImportError, "MySQLdb-1.2.1 or newer is required; you have %s" % MySQLdb.__version__
     15
    1316from MySQLdb.converters import conversions
    1417from MySQLdb.constants import FIELD_TYPE
    1518import types
    1619
    1720DatabaseError = Database.DatabaseError
    1821
     22# MySQLdb-1.2.1 supports the Python boolean type, and only uses datetime
     23# module for time-related columns; older versions could have used mx.DateTime
     24# or strings if there were no datetime module. However, MySQLdb still
     25# returns TIME columns as timedelta -- they are more like timedelta in
     26# terms of actual behavior as they are signed and include days -- and Django
     27# expects time, so we still need to override that.
     28
    1929django_conversions = conversions.copy()
    2030django_conversions.update({
    21     types.BooleanType: util.rev_typecast_boolean,
    22     FIELD_TYPE.DATETIME: util.typecast_timestamp,
    23     FIELD_TYPE.DATE: util.typecast_date,
    2431    FIELD_TYPE.TIME: util.typecast_time,
    25 })
     32    })
    2633
    27 # This is an extra debug layer over MySQL queries, to display warnings.
    28 # It's only used when DEBUG=True.
    29 class MysqlDebugWrapper:
    30     def __init__(self, cursor):
    31         self.cursor = cursor
     34# MySQLdb-1.2.1 and newer automatically makes use of SHOW WARNINGS
     35# on MySQL-4.1 and newer, so the MysqlDebugWrapper is unnecessary.
     36# Since the point is to raise Warnings as exceptions, this can be
     37# done with the Python warning module, and this is setup when the
     38# connection is created, and the standard util.CursorDebugWrapper
     39# can be used.
    3240
    33     def execute(self, sql, params=()):
    34         try:
    35             return self.cursor.execute(sql, params)
    36         except Database.Warning, w:
    37             self.cursor.execute("SHOW WARNINGS")
    38             raise Database.Warning, "%s: %s" % (w, self.cursor.fetchall())
    39 
    40     def executemany(self, sql, param_list):
    41         try:
    42             return self.cursor.executemany(sql, param_list)
    43         except Database.Warning, w:
    44             self.cursor.execute("SHOW WARNINGS")
    45             raise Database.Warning, "%s: %s" % (w, self.cursor.fetchall())
    46 
    47     def __getattr__(self, attr):
    48         if self.__dict__.has_key(attr):
    49             return self.__dict__[attr]
    50         else:
    51             return getattr(self.cursor, attr)
    52 
    5341try:
    5442    # Only exists in Python 2.4+
    5543    from threading import local
     
    7462
    7563    def cursor(self):
    7664        from django.conf import settings
     65        from warnings import filterwarnings
    7766        if not self._valid_connection():
    7867            kwargs = {
    7968                'user': settings.DATABASE_USER,
    8069                'db': settings.DATABASE_NAME,
    8170                'passwd': settings.DATABASE_PASSWORD,
    8271                'conv': django_conversions,
     72                'use_unicode': True,
     73                'charset': 'utf8',
     74                'sql_mode': "ANSI,TRADITIONAL",
    8375            }
    8476            if settings.DATABASE_HOST.startswith('/'):
    8577                kwargs['unix_socket'] = settings.DATABASE_HOST
     
    8981                kwargs['port'] = int(settings.DATABASE_PORT)
    9082            self.connection = Database.connect(**kwargs)
    9183        cursor = self.connection.cursor()
    92         if self.connection.get_server_info() >= '4.1':
    93             cursor.execute("SET NAMES 'utf8'")
    9484        if settings.DEBUG:
    95             return util.CursorDebugWrapper(MysqlDebugWrapper(cursor), self)
     85            filterwarnings("error", category=Database.Warning)
     86            return util.CursorDebugWrapper(cursor, self)
    9687        return cursor
    9788
    9889    def _commit(self):
     
    113104supports_constraints = True
    114105
    115106def quote_name(name):
    116     if name.startswith("`") and name.endswith("`"):
     107    if name.startswith('"') and name.endswith('"'):
    117108        return name # Quoting once is enough.
    118     return "`%s`" % name
     109    return '"%s"' % name
    119110
    120111dictfetchone = util.dictfetchone
    121112dictfetchmany = util.dictfetchmany
  • django/db/backends/mysql/introspection.py

     
    9292    FIELD_TYPE.LONG_BLOB: 'TextField',
    9393    FIELD_TYPE.VAR_STRING: 'CharField',
    9494}
     95
     96# these are only in MySQLdb-1.2.2b1 and newer
     97try:
     98    DATA_TYPES_REVERSE[FIELD_TYPE.BIT] = 'CharField'
     99    DATA_TYPES_REVERSE[FIELD_TYPE.VARCHAR] = 'CharField'
     100except AttributeError:
     101    pass
     102
Back to Top