Commits

Anonymous committed e4052f3

0.90-bugfixes: Backporting [4244] for those using legacy Django with psycopg1

Comments (0)

Files changed (1)

django/core/db/backends/postgresql.py

 
 DatabaseError = Database.DatabaseError
 
+def smart_basestring(s, charset):
+    if isinstance(s, unicode):
+        return s.encode(charset)
+    return s
+
+class UnicodeCursorWrapper(object):
+    """
+    A thin wrapper around psycopg cursors that allows them to accept Unicode
+    strings as params.
+
+    This is necessary because psycopg doesn't apply any DB quoting to
+    parameters that are Unicode strings. If a param is Unicode, this will
+    convert it to a bytestring using DEFAULT_CHARSET before passing it to
+    psycopg.
+    """
+    def __init__(self, cursor, charset):
+        self.cursor = cursor
+        self.charset = charset
+
+    def execute(self, sql, params=()):
+        return self.cursor.execute(sql, [smart_basestring(p, self.charset) for p in params])
+
+    def executemany(self, sql, param_list):
+        new_param_list = [tuple([smart_basestring(p, self.charset) for p in params]) for params in param_list]
+        return self.cursor.executemany(sql, new_param_list)
+
+    def __getattr__(self, attr):
+        if self.__dict__.has_key(attr):
+            return self.__dict__[attr]
+        else:
+            return getattr(self.cursor, attr)
+
 class DatabaseWrapper:
     def __init__(self):
         self.connection = None
             self.connection.set_isolation_level(1) # make transactions transparent to all cursors
         cursor = self.connection.cursor()
         cursor.execute("SET TIME ZONE %s", [TIME_ZONE])
+        cursor = UnicodeCursorWrapper(cursor, settings.DEFAULT_CHARSET)
         if DEBUG:
             return base.CursorDebugWrapper(cursor, self)
         return cursor