Code

Ticket #56: 56_bigint.diff

File 56_bigint.diff, 9.5 KB (added by pzinovkin, 2 years ago)

Alternative approach to fix #56

Line 
1diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py
2index 2762350..2c56ef6 100644
3--- a/django/db/backends/__init__.py
4+++ b/django/db/backends/__init__.py
5@@ -847,7 +847,8 @@ class BaseDatabaseOperations(object):
6         internal_type = field.get_internal_type()
7         if internal_type == 'DecimalField':
8             return value
9-        elif internal_type and internal_type.endswith('IntegerField') or internal_type == 'AutoField':
10+        elif (internal_type and internal_type.endswith('IntegerField')
11+                or internal_type.endswith('AutoField')):
12             return int(value)
13         elif internal_type in ('DateField', 'DateTimeField', 'TimeField'):
14             return value
15diff --git a/django/db/backends/mysql/creation.py b/django/db/backends/mysql/creation.py
16index 53bd57e..9876278 100644
17--- a/django/db/backends/mysql/creation.py
18+++ b/django/db/backends/mysql/creation.py
19@@ -6,6 +6,7 @@ class DatabaseCreation(BaseDatabaseCreation):
20     # be interpolated against the values of Field.__dict__ before being output.
21     # If a column type is set to None, it won't be included in the output.
22     data_types = {
23+        'BigAutoField':      'bigint AUTO_INCREMENT',
24         'AutoField':         'integer AUTO_INCREMENT',
25         'BooleanField':      'bool',
26         'CharField':         'varchar(%(max_length)s)',
27diff --git a/django/db/backends/oracle/creation.py b/django/db/backends/oracle/creation.py
28index 2f096f7..7e97271 100644
29--- a/django/db/backends/oracle/creation.py
30+++ b/django/db/backends/oracle/creation.py
31@@ -15,6 +15,7 @@ class DatabaseCreation(BaseDatabaseCreation):
32     # output (the "qn_" prefix is stripped before the lookup is performed.
33 
34     data_types = {
35+        'BigAutoField':                 'NUMBER(11)',
36         'AutoField':                    'NUMBER(11)',
37         'BooleanField':                 'NUMBER(1) CHECK (%(qn_column)s IN (0,1))',
38         'CharField':                    'NVARCHAR2(%(max_length)s)',
39diff --git a/django/db/backends/postgresql_psycopg2/creation.py b/django/db/backends/postgresql_psycopg2/creation.py
40index ca389b9..64223b1 100644
41--- a/django/db/backends/postgresql_psycopg2/creation.py
42+++ b/django/db/backends/postgresql_psycopg2/creation.py
43@@ -10,6 +10,7 @@ class DatabaseCreation(BaseDatabaseCreation):
44     # be interpolated against the values of Field.__dict__ before being output.
45     # If a column type is set to None, it won't be included in the output.
46     data_types = {
47+        'BigAutoField':      'bigserial',
48         'AutoField':         'serial',
49         'BooleanField':      'boolean',
50         'CharField':         'varchar(%(max_length)s)',
51diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py
52index 7ce9dd3..5a26344 100644
53--- a/django/db/backends/sqlite3/base.py
54+++ b/django/db/backends/sqlite3/base.py
55@@ -191,7 +191,8 @@ class DatabaseOperations(BaseDatabaseOperations):
56         internal_type = field.get_internal_type()
57         if internal_type == 'DecimalField':
58             return util.typecast_decimal(field.format_number(value))
59-        elif internal_type and internal_type.endswith('IntegerField') or internal_type == 'AutoField':
60+        elif (internal_type and internal_type.endswith('IntegerField')
61+                or internal_type.endswith('AutoField')):
62             return int(value)
63         elif internal_type == 'DateField':
64             return parse_date(value)
65diff --git a/django/db/backends/sqlite3/creation.py b/django/db/backends/sqlite3/creation.py
66index efdc457..51ceca9 100644
67--- a/django/db/backends/sqlite3/creation.py
68+++ b/django/db/backends/sqlite3/creation.py
69@@ -7,6 +7,7 @@ class DatabaseCreation(BaseDatabaseCreation):
70     # thing" given more verbose field definitions, so leave them as is so that
71     # schema inspection is more useful.
72     data_types = {
73+        'BigAutoField':                 'integer',
74         'AutoField':                    'integer',
75         'BooleanField':                 'bool',
76         'CharField':                    'varchar(%(max_length)s)',
77diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
78index f694958..668f367 100644
79--- a/django/db/models/fields/__init__.py
80+++ b/django/db/models/fields/__init__.py
81@@ -205,6 +205,13 @@ class Field(object):
82         self.run_validators(value)
83         return value
84 
85+    def _internal_to_db_type(self, internal_type, connection):
86+        data = DictWrapper(self.__dict__, connection.ops.quote_name, "qn_")
87+        try:
88+            return connection.creation.data_types[internal_type] % data
89+        except KeyError:
90+            return None
91+
92     def db_type(self, connection):
93         """
94         Returns the database column data type for this field, for the provided
95@@ -225,12 +232,14 @@ class Field(object):
96         # mapped to one of the built-in Django field types. In this case, you
97         # can implement db_type() instead of get_internal_type() to specify
98         # exactly which wacky database column type you want to use.
99-        data = DictWrapper(self.__dict__, connection.ops.quote_name, "qn_")
100-        try:
101-            return (connection.creation.data_types[self.get_internal_type()]
102-                    % data)
103-        except KeyError:
104-            return None
105+        return self._internal_to_db_type(self.get_internal_type(), connection)
106+
107+    def rel_db_type(self, connection):
108+        """
109+        Returns the database column data type for related field referencing
110+        to this.
111+        """
112+        return self.db_type(connection)
113 
114     @property
115     def unique(self):
116@@ -514,14 +523,19 @@ class AutoField(Field):
117         'invalid': _(u"'%s' value must be an integer."),
118     }
119 
120-    def __init__(self, *args, **kwargs):
121+    def __init__(self, verbose_name=None, name=None, big=False, **kwargs):
122         assert kwargs.get('primary_key', False) is True, \
123                "%ss must have primary_key=True." % self.__class__.__name__
124         kwargs['blank'] = True
125-        Field.__init__(self, *args, **kwargs)
126+        self.big = big
127+        Field.__init__(self, verbose_name, name, **kwargs)
128 
129     def get_internal_type(self):
130-        return "AutoField"
131+        return 'AutoField' if not self.big else 'BigAutoField'
132+
133+    def rel_db_type(self, connection):
134+        db_type = 'IntegerField' if not self.big else 'BigIntegerField'
135+        return self._internal_to_db_type(db_type, connection)
136 
137     def to_python(self, value):
138         if value is None:
139@@ -1139,6 +1153,11 @@ class PositiveIntegerField(IntegerField):
140     def get_internal_type(self):
141         return "PositiveIntegerField"
142 
143+    def rel_db_type(self, connection):
144+        if connection.features.related_fields_match_type:
145+            return self.db_type(connection)
146+        return self._internal_to_db_type('IntegerField', connection)
147+
148     def formfield(self, **kwargs):
149         defaults = {'min_value': 0}
150         defaults.update(kwargs)
151@@ -1150,6 +1169,11 @@ class PositiveSmallIntegerField(IntegerField):
152     def get_internal_type(self):
153         return "PositiveSmallIntegerField"
154 
155+    def rel_db_type(self, connection):
156+        if connection.features.related_fields_match_type:
157+            return self.db_type(connection)
158+        return self._internal_to_db_type('IntegerField', connection)
159+
160     def formfield(self, **kwargs):
161         defaults = {'min_value': 0}
162         defaults.update(kwargs)
163diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
164index a16f955..0783590 100644
165--- a/django/db/models/fields/related.py
166+++ b/django/db/models/fields/related.py
167@@ -1018,19 +1018,8 @@ class ForeignKey(RelatedField, Field):
168         return super(ForeignKey, self).formfield(**defaults)
169 
170     def db_type(self, connection):
171-        # The database column type of a ForeignKey is the column type
172-        # of the field to which it points. An exception is if the ForeignKey
173-        # points to an AutoField/PositiveIntegerField/PositiveSmallIntegerField,
174-        # in which case the column type is simply that of an IntegerField.
175-        # If the database needs similar types for key fields however, the only
176-        # thing we can do is making AutoField an IntegerField.
177         rel_field = self.rel.get_related_field()
178-        if (isinstance(rel_field, AutoField) or
179-                (not connection.features.related_fields_match_type and
180-                isinstance(rel_field, (PositiveIntegerField,
181-                                       PositiveSmallIntegerField)))):
182-            return IntegerField().db_type(connection=connection)
183-        return rel_field.db_type(connection=connection)
184+        return rel_field.rel_db_type(connection=connection)
185 
186 class OneToOneField(ForeignKey):
187     """
188diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt
189index eab7ad9..d88368a 100644
190--- a/docs/ref/models/fields.txt
191+++ b/docs/ref/models/fields.txt
192@@ -320,13 +320,22 @@ Field types
193 ``AutoField``
194 -------------
195 
196-.. class:: AutoField(**options)
197+.. class:: AutoField([big=False, **options])
198 
199 An :class:`IntegerField` that automatically increments
200 according to available IDs. You usually won't need to use this directly; a
201 primary key field will automatically be added to your model if you don't specify
202 otherwise. See :ref:`automatic-primary-key-fields`.
203 
204+.. attribute:: AutoField.big
205+
206+    .. versionadded:: 1.5
207+
208+    Optional.  Either ``False`` or ``True``.  Default is ``False``. Allow you
209+    to use bigint for storing field values. This extends values range up to
210+    max 64 bit integer (from 1 to 9223372036854775807).
211+
212+
213 ``BigIntegerField``
214 -------------------
215