Django

Code

root/django/trunk/django/db/backends/util.py

Revision 9394, 4.1 kB (checked in by kmtracey, 2 weeks ago)

Fixed #5079 -- Avoid converting Decimals to floats during save to the database.

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