Django

Code

Show
Ignore:
Timestamp:
07/02/07 02:43:36 (2 years ago)
Author:
mtredinnick
Message:

unicode: Added Unicode support for the Oracle backend. All tests pass.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/unicode/django/db/backends/oracle/base.py

    r5531 r5584  
    77from django.conf import settings 
    88from django.db.backends import util 
     9from django.utils.datastructures import SortedDict 
     10from django.utils.encoding import smart_str, force_unicode 
     11import datetime 
     12import os 
     13 
     14# Oracle takes client-side character set encoding from the environment. 
     15os.environ['NLS_LANG'] = '.UTF8' 
    916try: 
    1017    import cx_Oracle as Database 
     
    1219    from django.core.exceptions import ImproperlyConfigured 
    1320    raise ImproperlyConfigured, "Error loading cx_Oracle module: %s" % e 
    14 import datetime 
    15 from django.utils.datastructures import SortedDict 
    1621 
    1722 
     
    4651                self.connection = Database.connect(conn_string, **self.options) 
    4752        cursor = FormatStylePlaceholderCursor(self.connection) 
    48         # default arraysize of 1 is highly sub-optimal 
     53        # Default arraysize of 1 is highly sub-optimal. 
    4954        cursor.arraysize = 100 
    50         # set oracle date to ansi date format 
     55        # Set oracle date to ansi date format. 
    5156        cursor.execute("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD'") 
    5257        cursor.execute("ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'") 
     
    7984class FormatStylePlaceholderCursor(Database.Cursor): 
    8085    """ 
    81     Django uses "format" (e.g. '%s') style placeholders, but Oracle uses ":var" style. 
    82     This fixes it -- but note that if you want to use a literal "%s" in a query, 
    83     you'll need to use "%%s". 
     86    Django uses "format" (e.g. '%s') style placeholders, but Oracle uses ":var" 
     87    style. This fixes it -- but note that if you want to use a literal "%s" in 
     88    a query, you'll need to use "%%s". 
     89 
     90    We also do automatic conversion between Unicode on the Python side and 
     91    UTF-8 -- for talking to Oracle -- in here. 
    8492    """ 
     93    charset = 'utf-8' 
     94 
    8595    def _rewrite_args(self, query, params=None): 
    8696        if params is None: 
    8797            params = [] 
    8898        else: 
    89             # cx_Oracle can't handle unicode parameters, so cast to str for now 
    90             for i, param in enumerate(params): 
    91                 if type(param) == unicode: 
    92                     try: 
    93                         params[i] = param.encode('utf-8') 
    94                     except UnicodeError: 
    95                         params[i] = str(param) 
     99            params = self._format_params(params) 
    96100        args = [(':arg%d' % i) for i in range(len(params))] 
    97         query = query % tuple(args) 
     101        query = smart_str(query, self.charset) % tuple(args) 
    98102        # cx_Oracle wants no trailing ';' for SQL statements.  For PL/SQL, it 
    99103        # it does want a trailing ';' but not a trailing '/'.  However, these 
     
    104108        return query, params 
    105109 
     110    def _format_params(self, params): 
     111        if isinstance(params, dict): 
     112            result = {} 
     113            charset = self.charset 
     114            for key, value in params.items(): 
     115                result[smart_str(key, charset)] = smart_str(value, charset) 
     116            return result 
     117        else: 
     118            return tuple([smart_str(p, self.charset, True) for p in params]) 
     119 
    106120    def execute(self, query, params=None): 
    107121        query, params = self._rewrite_args(query, params) 
     
    111125        query, params = self._rewrite_args(query, params) 
    112126        return Database.Cursor.executemany(self, query, params) 
     127 
     128    def fetchone(self): 
     129        return to_unicode(Database.Cursor.fetchone(self)) 
     130 
     131    def fetchmany(self, size=None): 
     132        if size is None: 
     133            size = self.arraysize 
     134        return tuple([tuple([to_unicode(e) for e in r]) for r in Database.Cursor.fetchmany(self, size)]) 
     135 
     136    def fetchall(self): 
     137        return tuple([tuple([to_unicode(e) for e in r]) for r in Database.Cursor.fetchall(self)]) 
     138 
     139def to_unicode(s): 
     140    """ 
     141    Convert strings to Unicode objects (and return all other data types 
     142    unchanged). 
     143    """ 
     144    if isinstance(s, basestring): 
     145        return force_unicode(s) 
     146    return s 
    113147 
    114148def quote_name(name): 
  • django/branches/unicode/django/db/backends/oracle/creation.py

    r5531 r5584  
    99    'AutoField':                    'NUMBER(11)', 
    1010    'BooleanField':                 'NUMBER(1) CHECK (%(column)s IN (0,1))', 
    11     'CharField':                    'VARCHAR2(%(maxlength)s)', 
     11    'CharField':                    'NVARCHAR2(%(maxlength)s)', 
    1212    'CommaSeparatedIntegerField':   'VARCHAR2(%(maxlength)s)', 
    1313    'DateField':                    'DATE', 
    1414    'DateTimeField':                'TIMESTAMP', 
    1515    'DecimalField':                 'NUMBER(%(max_digits)s, %(decimal_places)s)', 
    16     'FileField':                    'VARCHAR2(100)', 
    17     'FilePathField':                'VARCHAR2(100)', 
     16    'FileField':                    'NVARCHAR2(100)', 
     17    'FilePathField':                'NVARCHAR2(100)', 
    1818    'FloatField':                   'DOUBLE PRECISION', 
    19     'ImageField':                   'VARCHAR2(100)', 
     19    'ImageField':                   'NVARCHAR2(100)', 
    2020    'IntegerField':                 'NUMBER(11)', 
    2121    'IPAddressField':               'VARCHAR2(15)', 
     
    2626    'PositiveIntegerField':         'NUMBER(11) CHECK (%(column)s >= 0)', 
    2727    'PositiveSmallIntegerField':    'NUMBER(11) CHECK (%(column)s >= 0)', 
    28     'SlugField':                    'VARCHAR2(50)', 
     28    'SlugField':                    'NVARCHAR2(50)', 
    2929    'SmallIntegerField':            'NUMBER(11)', 
    3030    'TextField':                    'NCLOB',