Ticket #2417: patch.txt

File patch.txt, 9.2 KB (added by alex@…, 16 years ago)

latest version of the patch (2008.07.28) - fix for MySQL converters

Line 
1Index: django/db/models/fields/__init__.py
2===================================================================
3--- django/db/models/fields/__init__.py (revision 8020)
4+++ django/db/models/fields/__init__.py (working copy)
5@@ -518,6 +518,25 @@
6 defaults.update(kwargs)
7 return super(CharField, self).formfield(**defaults)
8
9+class BinaryField(Field):
10+ """Sometimes we have fields that need to store a small amount of binary
11+ data. This is different then a varchar on postgresql at least because it
12+ will not allow fields that are just nul bytes.
13+ """
14+
15+ def get_internal_type(self):
16+ return "BinaryField"
17+
18+
19+class BlobField(Field):
20+ """Sometimes we have fields that need to store a large amounts of binary
21+ data.
22+ """
23+
24+ def get_internal_type(self):
25+ return "BlobField"
26+
27+
28 # TODO: Maybe move this into contrib, because it's specialized.
29 class CommaSeparatedIntegerField(CharField):
30 def get_manipulator_field_objs(self):
31Index: django/db/backends/postgresql/introspection.py
32===================================================================
33--- django/db/backends/postgresql/introspection.py (revision 8020)
34+++ django/db/backends/postgresql/introspection.py (working copy)
35@@ -71,6 +71,7 @@
36 # Maps type codes to Django Field types.
37 DATA_TYPES_REVERSE = {
38 16: 'BooleanField',
39+ 17: 'BlobField',
40 21: 'SmallIntegerField',
41 23: 'IntegerField',
42 25: 'TextField',
43Index: django/db/backends/postgresql/creation.py
44===================================================================
45--- django/db/backends/postgresql/creation.py (revision 8020)
46+++ django/db/backends/postgresql/creation.py (working copy)
47@@ -4,6 +4,8 @@
48 # If a column type is set to None, it won't be included in the output.
49 DATA_TYPES = {
50 'AutoField': 'serial',
51+ 'BinaryField': 'bytea',
52+ 'BlobField': 'bytea',
53 'BooleanField': 'boolean',
54 'CharField': 'varchar(%(max_length)s)',
55 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
56Index: django/db/backends/sqlite3/creation.py
57===================================================================
58--- django/db/backends/sqlite3/creation.py (revision 8020)
59+++ django/db/backends/sqlite3/creation.py (working copy)
60@@ -3,6 +3,8 @@
61 # schema inspection is more useful.
62 DATA_TYPES = {
63 'AutoField': 'integer',
64+ 'BinaryField': 'BLOB',
65+ 'BlobField': 'BLOB',
66 'BooleanField': 'bool',
67 'CharField': 'varchar(%(max_length)s)',
68 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
69Index: django/db/backends/mysql/base.py
70===================================================================
71--- django/db/backends/mysql/base.py (revision 8015)
72+++ django/db/backends/mysql/base.py (working copy)
73@@ -21,7 +21,8 @@
74 raise ImproperlyConfigured("MySQLdb-1.2.1p2 or newer is required; you have %s" % Database.__version__)
75
76 from MySQLdb.converters import conversions
77-from MySQLdb.constants import FIELD_TYPE
78+from MySQLdb.constants import FIELD_TYPE,FLAG
79+from django.utils.encoding import smart_unicode
80 import re
81
82 # Raise exceptions for database warnings if DEBUG is on
83@@ -40,10 +41,22 @@
84 # behavior as they are signed and include days -- and Django expects time, so
85 # we still need to override that.
86 django_conversions = conversions.copy()
87+
88+binstr_conversion = [(FLAG.BINARY, buffer),
89+ (FLAG.BLOB, smart_unicode),
90+ ]
91+
92 django_conversions.update({
93 FIELD_TYPE.TIME: util.typecast_time,
94 FIELD_TYPE.DECIMAL: util.typecast_decimal,
95 FIELD_TYPE.NEWDECIMAL: util.typecast_decimal,
96+ FIELD_TYPE.TINY_BLOB: binstr_conversion,
97+ FIELD_TYPE.MEDIUM_BLOB: binstr_conversion,
98+ FIELD_TYPE.LONG_BLOB: binstr_conversion,
99+ FIELD_TYPE.BLOB: binstr_conversion,
100+ FIELD_TYPE.VARCHAR: binstr_conversion,
101+ FIELD_TYPE.VAR_STRING: binstr_conversion,
102+ FIELD_TYPE.STRING: binstr_conversion,
103 })
104
105 # This should match the numerical portion of the version numbers (we can treat
106Index: django/db/backends/mysql/introspection.py
107===================================================================
108--- django/db/backends/mysql/introspection.py (revision 8020)
109+++ django/db/backends/mysql/introspection.py (working copy)
110@@ -75,7 +75,10 @@
111 return indexes
112
113 DATA_TYPES_REVERSE = {
114- FIELD_TYPE.BLOB: 'TextField',
115+ FIELD_TYPE.BLOB: 'BlobField',
116+ FIELD_TYPE.LONG_BLOB: 'BlobField',
117+ FIELD_TYPE.TINY_BLOB: 'BlobField',
118+ FIELD_TYPE.MEDIUM_BLOB: 'BlobField',
119 FIELD_TYPE.CHAR: 'CharField',
120 FIELD_TYPE.DECIMAL: 'DecimalField',
121 FIELD_TYPE.DATE: 'DateField',
122Index: django/db/backends/mysql/creation.py
123===================================================================
124--- django/db/backends/mysql/creation.py (revision 8020)
125+++ django/db/backends/mysql/creation.py (working copy)
126@@ -4,6 +4,8 @@
127 # If a column type is set to None, it won't be included in the output.
128 DATA_TYPES = {
129 'AutoField': 'integer AUTO_INCREMENT',
130+ 'BinaryField': 'varbinary(%(max_length)s)',
131+ 'BlobField': 'blob',
132 'BooleanField': 'bool',
133 'CharField': 'varchar(%(max_length)s)',
134 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
135Index: django/db/backends/__init__.py
136===================================================================
137--- django/db/backends/__init__.py (revision 8020)
138+++ django/db/backends/__init__.py (working copy)
139@@ -143,8 +143,11 @@
140 """
141 from django.utils.encoding import smart_unicode, force_unicode
142
143- # Convert params to contain Unicode values.
144- to_unicode = lambda s: force_unicode(s, strings_only=True)
145+ def to_unicode(s):
146+ if isinstance(s,buffer):
147+ return u'<binary data buffer size %d>' % len(s)
148+ return force_unicode(s, strings_only=True)
149+
150 if isinstance(params, (list, tuple)):
151 u_params = tuple([to_unicode(val) for val in params])
152 else:
153Index: django/db/backends/postgresql_psycopg2/introspection.py
154===================================================================
155--- django/db/backends/postgresql_psycopg2/introspection.py (revision 8020)
156+++ django/db/backends/postgresql_psycopg2/introspection.py (working copy)
157@@ -68,6 +68,7 @@
158 # Maps type codes to Django Field types.
159 DATA_TYPES_REVERSE = {
160 16: 'BooleanField',
161+ 17: 'BlobField',
162 21: 'SmallIntegerField',
163 23: 'IntegerField',
164 25: 'TextField',
165Index: tests/modeltests/binary/__init__.py
166===================================================================
167Index: tests/modeltests/binary/tests.py
168===================================================================
169--- tests/modeltests/binary/tests.py (revision 0)
170+++ tests/modeltests/binary/tests.py (revision 0)
171@@ -0,0 +1,67 @@
172+#!/usr/bin/python
173+# encoding: utf-8
174+
175+from models import Document, BinaryFieldTest
176+
177+import unittest
178+
179+
180+class BlobFieldTests( unittest.TestCase ):
181+
182+ def test_blob(self):
183+ test_title = u'Hi there! привет!'
184+ test_descr = u'описание документа'
185+
186+ s = ''
187+ for i in range(0,256):
188+ s += chr(i)
189+ s+= '\xff\xff'
190+
191+
192+ test_data = buffer(s)
193+
194+ doc = Document(title = test_title,
195+ description = test_descr,
196+ document = test_data)
197+ doc.save()
198+ doc_id = doc.id
199+ doc = None
200+ doc = Document.objects.get(id=doc_id)
201+ assert doc.title == test_title, type(doc.title)
202+ assert doc.description == test_descr, type(doc.description)
203+ assert doc.document == test_data, type(doc.document)
204+
205+class BinaryFieldTests( unittest.TestCase ):
206+
207+ def test_binary(self):
208+ test_title = u'Hi there! привет!'
209+
210+ s = ''
211+ for i in range(0,10):
212+ s += chr(i)
213+
214+ s+= '\xff\xff'
215+
216+ test_data = buffer(s)
217+
218+
219+ tst = BinaryFieldTest(title = test_title,
220+ binfield = test_data)
221+ tst.save()
222+ tst_id = tst.id
223+ tst = None
224+ tst = BinaryFieldTest.objects.get(id=tst_id)
225+ assert tst.title == test_title, type(tst.title)
226+ assert tst.binfield == test_data, type(tst.binfield)
227+
228+
229+def test_suite():
230+ return unittest.TestSuite((
231+ unittest.makeSuite(BlobFieldTests),
232+ unittest.makeSuite(BinaryFieldTests)
233+ ))
234+
235+
236+
237+if __name__ == '__main__':
238+ unittest.main(defaultTest='test_suite')
239Index: tests/modeltests/binary/models.py
240===================================================================
241--- tests/modeltests/binary/models.py (revision 0)
242+++ tests/modeltests/binary/models.py (revision 0)
243@@ -0,0 +1,18 @@
244+"""
245+BlobField and BinaryField tests
246+
247+"""
248+
249+from django.db import models
250+
251+# Create your models here.
252+class Document(models.Model):
253+ title = models.CharField(max_length=50)
254+ description = models.TextField()
255+ document = models.BlobField()
256+
257+class BinaryFieldTest(models.Model):
258+ title = models.CharField(max_length=20)
259+ binfield = models.BinaryField(max_length=20)
260+
261+
Back to Top