summaryrefslogtreecommitdiff
path: root/django/db/backends/mysql/base.py
diff options
context:
space:
mode:
Diffstat (limited to 'django/db/backends/mysql/base.py')
-rw-r--r--django/db/backends/mysql/base.py73
1 files changed, 36 insertions, 37 deletions
diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py
index 4ccb1fe564..94718595cb 100644
--- a/django/db/backends/mysql/base.py
+++ b/django/db/backends/mysql/base.py
@@ -10,6 +10,15 @@ try:
except ImportError, e:
from django.core.exceptions import ImproperlyConfigured
raise ImproperlyConfigured, "Error loading MySQLdb module: %s" % e
+
+# We want version (1, 2, 1, 'final', 2) or later. We can't just use
+# lexicographic ordering in this check because then (1, 2, 1, 'gamma')
+# inadvertently passes the version test.
+version = Database.version_info
+if (version < (1,2,1) or (version[:3] == (1, 2, 1) and
+ (len(version) < 5 or version[3] != 'final' or version[4] < 2))):
+ raise ImportError, "MySQLdb-1.2.1p2 or newer is required; you have %s" % Database.__version__
+
from MySQLdb.converters import conversions
from MySQLdb.constants import FIELD_TYPE
import types
@@ -17,11 +26,14 @@ import re
DatabaseError = Database.DatabaseError
+# MySQLdb-1.2.1 supports the Python boolean type, and only uses datetime
+# module for time-related columns; older versions could have used mx.DateTime
+# or strings if there were no datetime module. However, MySQLdb still returns
+# TIME columns as timedelta -- they are more like timedelta in terms of actual
+# behavior as they are signed and include days -- and Django expects time, so
+# we still need to override that.
django_conversions = conversions.copy()
django_conversions.update({
- types.BooleanType: util.rev_typecast_boolean,
- FIELD_TYPE.DATETIME: util.typecast_timestamp,
- FIELD_TYPE.DATE: util.typecast_date,
FIELD_TYPE.TIME: util.typecast_time,
})
@@ -31,31 +43,12 @@ django_conversions.update({
# http://dev.mysql.com/doc/refman/5.0/en/news.html .
server_version_re = re.compile(r'(\d{1,2})\.(\d{1,2})\.(\d{1,2})')
-# This is an extra debug layer over MySQL queries, to display warnings.
-# It's only used when DEBUG=True.
-class MysqlDebugWrapper:
- def __init__(self, cursor):
- self.cursor = cursor
-
- def execute(self, sql, params=()):
- try:
- return self.cursor.execute(sql, params)
- except Database.Warning, w:
- self.cursor.execute("SHOW WARNINGS")
- raise Database.Warning, "%s: %s" % (w, self.cursor.fetchall())
-
- def executemany(self, sql, param_list):
- try:
- return self.cursor.executemany(sql, param_list)
- except Database.Warning, w:
- self.cursor.execute("SHOW WARNINGS")
- raise Database.Warning, "%s: %s" % (w, self.cursor.fetchall())
-
- def __getattr__(self, attr):
- if self.__dict__.has_key(attr):
- return self.__dict__[attr]
- else:
- return getattr(self.cursor, attr)
+# MySQLdb-1.2.1 and newer automatically makes use of SHOW WARNINGS on
+# MySQL-4.1 and newer, so the MysqlDebugWrapper is unnecessary. Since the
+# point is to raise Warnings as exceptions, this can be done with the Python
+# warning module, and this is setup when the connection is created, and the
+# standard util.CursorDebugWrapper can be used. Also, using sql_mode
+# TRADITIONAL will automatically cause most warnings to be treated as errors.
try:
# Only exists in Python 2.4+
@@ -83,35 +76,41 @@ class DatabaseWrapper(local):
def cursor(self):
from django.conf import settings
+ from warnings import filterwarnings
if not self._valid_connection():
kwargs = {
- 'user': settings.DATABASE_USER,
- 'db': settings.DATABASE_NAME,
- 'passwd': settings.DATABASE_PASSWORD,
'conv': django_conversions,
+ 'charset': 'utf8',
+ 'use_unicode': False,
}
+ if settings.DATABASE_USER:
+ kwargs['user'] = settings.DATABASE_USER
+ if settings.DATABASE_NAME:
+ kwargs['db'] = settings.DATABASE_NAME
+ if settings.DATABASE_PASSWORD:
+ kwargs['passwd'] = settings.DATABASE_PASSWORD
if settings.DATABASE_HOST.startswith('/'):
kwargs['unix_socket'] = settings.DATABASE_HOST
- else:
+ elif settings.DATABASE_HOST:
kwargs['host'] = settings.DATABASE_HOST
if settings.DATABASE_PORT:
kwargs['port'] = int(settings.DATABASE_PORT)
kwargs.update(self.options)
self.connection = Database.connect(**kwargs)
cursor = self.connection.cursor()
- if self.connection.get_server_info() >= '4.1':
- cursor.execute("SET NAMES 'utf8'")
else:
cursor = self.connection.cursor()
if settings.DEBUG:
- return util.CursorDebugWrapper(MysqlDebugWrapper(cursor), self)
+ filterwarnings("error", category=Database.Warning)
+ return util.CursorDebugWrapper(cursor, self)
return cursor
def _commit(self):
- self.connection.commit()
+ if self.connection is not None:
+ self.connection.commit()
def _rollback(self):
- if self.connection:
+ if self.connection is not None:
try:
self.connection.rollback()
except Database.NotSupportedError: