web/lib/django/db/backends/util.py
author ymh <ymh.work@gmail.com>
Thu, 05 Aug 2010 17:28:09 +0200
changeset 50 012451a812f1
parent 38 77b6da96e6f1
permissions -rw-r--r--
Merge with a2711e44ba5de8b1675d7e0ee6aaa4a6c56a9b46
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
38
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
import datetime
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
import decimal
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
from time import time
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
from django.utils.hashcompat import md5_constructor
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
class CursorDebugWrapper(object):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
    def __init__(self, cursor, db):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
        self.cursor = cursor
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
        self.db = db # Instance of a BaseDatabaseWrapper subclass
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
    def execute(self, sql, params=()):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
        start = time()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
        try:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
            return self.cursor.execute(sql, params)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
        finally:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
            stop = time()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
            sql = self.db.ops.last_executed_query(self.cursor, sql, params)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
            self.db.queries.append({
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
                'sql': sql,
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
                'time': "%.3f" % (stop - start),
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
            })
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
    def executemany(self, sql, param_list):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
        start = time()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
        try:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
            return self.cursor.executemany(sql, param_list)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
        finally:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
            stop = time()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
            self.db.queries.append({
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
                'sql': '%s times: %s' % (len(param_list), sql),
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
                'time': "%.3f" % (stop - start),
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
            })
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
    def __getattr__(self, attr):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
        if attr in self.__dict__:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
            return self.__dict__[attr]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
        else:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
            return getattr(self.cursor, attr)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
    def __iter__(self):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
        return iter(self.cursor)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
###############################################
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
# Converters from database (string) to Python #
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
###############################################
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
def typecast_date(s):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
    return s and datetime.date(*map(int, s.split('-'))) or None # returns None if s is null
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
def typecast_time(s): # does NOT store time zone information
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
    if not s: return None
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
    hour, minutes, seconds = s.split(':')
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
    if '.' in seconds: # check whether seconds have a fractional part
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
        seconds, microseconds = seconds.split('.')
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
    else:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
        microseconds = '0'
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
    return datetime.time(int(hour), int(minutes), int(seconds), int(float('.'+microseconds) * 1000000))
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
def typecast_timestamp(s): # does NOT store time zone information
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
    # "2005-07-29 15:48:00.590358-05"
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
    # "2005-07-29 09:56:00-05"
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
    if not s: return None
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
    if not ' ' in s: return typecast_date(s)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
    d, t = s.split()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
    # Extract timezone information, if it exists. Currently we just throw
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
    # it away, but in the future we may make use of it.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
    if '-' in t:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
        t, tz = t.split('-', 1)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
        tz = '-' + tz
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
    elif '+' in t:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
        t, tz = t.split('+', 1)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
        tz = '+' + tz
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
    else:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
        tz = ''
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
    dates = d.split('-')
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
    times = t.split(':')
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
    seconds = times[2]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
    if '.' in seconds: # check whether seconds have a fractional part
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
        seconds, microseconds = seconds.split('.')
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
    else:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
        microseconds = '0'
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
    return datetime.datetime(int(dates[0]), int(dates[1]), int(dates[2]),
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
        int(times[0]), int(times[1]), int(seconds), int(float('.'+microseconds) * 1000000))
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
def typecast_boolean(s):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
    if s is None: return None
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
    if not s: return False
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
    return str(s)[0].lower() == 't'
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
def typecast_decimal(s):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
    if s is None or s == '':
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
        return None
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
    return decimal.Decimal(s)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
###############################################
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
# Converters from Python to database (string) #
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
###############################################
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
def rev_typecast_boolean(obj, d):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
    return obj and '1' or '0'
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
def rev_typecast_decimal(d):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
    if d is None:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
        return None
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
    return str(d)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   107
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   108
def truncate_name(name, length=None):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
    """Shortens a string to a repeatable mangled version with the given length.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
    if length is None or len(name) <= length:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
        return name
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   114
    hash = md5_constructor(name).hexdigest()[:4]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   115
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   116
    return '%s%s' % (name[:length-4], hash)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   117
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   118
def format_number(value, max_digits, decimal_places):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   119
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   120
    Formats a number into a string with the requisite number of digits and
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   121
    decimal places.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   122
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   123
    if isinstance(value, decimal.Decimal):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   124
        context = decimal.getcontext().copy()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   125
        context.prec = max_digits
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   126
        return u'%s' % str(value.quantize(decimal.Decimal(".1") ** decimal_places, context=context))
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   127
    else:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   128
        return u"%.*f" % (decimal_places, value)