Ticket #56: 56_bigint_new.diff

File 56_bigint_new.diff, 13.1 KB (added by pzinovkin, 12 years ago)

with tests

  • django/db/backends/__init__.py

    diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py
    index 649f807..3802b1c 100644
    a b class BaseDatabaseOperations(object):  
    889889            return value
    890890        elif internal_type == 'FloatField':
    891891            return float(value)
    892         elif (internal_type and (internal_type.endswith('IntegerField')
    893                                  or internal_type == 'AutoField')):
     892        elif (internal_type and internal_type.endswith('IntegerField')
     893                or internal_type.endswith('AutoField')):
    894894            return int(value)
    895895        elif internal_type in ('DateField', 'DateTimeField', 'TimeField'):
    896896            return value
  • django/db/backends/mysql/base.py

    diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py
    index cec3b04..fe2ebab 100644
    a b def adapt_datetime_with_timezone_support(value, conv):  
    6464    # Equivalent to DateTimeField.get_db_prep_value. Used only by raw SQL.
    6565    if settings.USE_TZ:
    6666        if timezone.is_naive(value):
    67             warnings.warn("SQLite received a naive datetime (%s)"
     67            warnings.warn("MySQL received a naive datetime (%s)"
    6868                          " while time zone support is active." % value,
    6969                          RuntimeWarning)
    7070            default_timezone = timezone.get_default_timezone()
  • django/db/backends/mysql/creation.py

    diff --git a/django/db/backends/mysql/creation.py b/django/db/backends/mysql/creation.py
    index 53bd57e..9876278 100644
    a b class DatabaseCreation(BaseDatabaseCreation):  
    66    # be interpolated against the values of Field.__dict__ before being output.
    77    # If a column type is set to None, it won't be included in the output.
    88    data_types = {
     9        'BigAutoField':      'bigint AUTO_INCREMENT',
    910        'AutoField':         'integer AUTO_INCREMENT',
    1011        'BooleanField':      'bool',
    1112        'CharField':         'varchar(%(max_length)s)',
  • django/db/backends/oracle/creation.py

    diff --git a/django/db/backends/oracle/creation.py b/django/db/backends/oracle/creation.py
    index d9bf3df..0059644 100644
    a b class DatabaseCreation(BaseDatabaseCreation):  
    1616    # output (the "qn_" prefix is stripped before the lookup is performed.
    1717
    1818    data_types = {
     19        'BigAutoField':                 'NUMBER(19)',
    1920        'AutoField':                    'NUMBER(11)',
    2021        'BooleanField':                 'NUMBER(1) CHECK (%(qn_column)s IN (0,1))',
    2122        'CharField':                    'NVARCHAR2(%(max_length)s)',
  • django/db/backends/postgresql_psycopg2/creation.py

    diff --git a/django/db/backends/postgresql_psycopg2/creation.py b/django/db/backends/postgresql_psycopg2/creation.py
    index ca389b9..64223b1 100644
    a b class DatabaseCreation(BaseDatabaseCreation):  
    1010    # be interpolated against the values of Field.__dict__ before being output.
    1111    # If a column type is set to None, it won't be included in the output.
    1212    data_types = {
     13        'BigAutoField':      'bigserial',
    1314        'AutoField':         'serial',
    1415        'BooleanField':      'boolean',
    1516        'CharField':         'varchar(%(max_length)s)',
  • django/db/backends/sqlite3/base.py

    diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py
    index 31a16b6..83aedbe 100644
    a b class DatabaseOperations(BaseDatabaseOperations):  
    210210        internal_type = field.get_internal_type()
    211211        if internal_type == 'DecimalField':
    212212            return util.typecast_decimal(field.format_number(value))
    213         elif internal_type and internal_type.endswith('IntegerField') or internal_type == 'AutoField':
     213        elif (internal_type and internal_type.endswith('IntegerField')
     214                or internal_type.endswith('AutoField')):
    214215            return int(value)
    215216        elif internal_type == 'DateField':
    216217            return parse_date(value)
  • django/db/backends/sqlite3/creation.py

    diff --git a/django/db/backends/sqlite3/creation.py b/django/db/backends/sqlite3/creation.py
    index c022b56..8a9952c 100644
    a b class DatabaseCreation(BaseDatabaseCreation):  
    88    # thing" given more verbose field definitions, so leave them as is so that
    99    # schema inspection is more useful.
    1010    data_types = {
     11        'BigAutoField':                 'integer',
    1112        'AutoField':                    'integer',
    1213        'BooleanField':                 'bool',
    1314        'CharField':                    'varchar(%(max_length)s)',
  • django/db/models/fields/__init__.py

    diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
    index d07851b..2ce0f3c 100644
    a b class Field(object):  
    212212        self.run_validators(value)
    213213        return value
    214214
     215    def _internal_to_db_type(self, internal_type, connection):
     216        data = DictWrapper(self.__dict__, connection.ops.quote_name, "qn_")
     217        try:
     218            return connection.creation.data_types[internal_type] % data
     219        except KeyError:
     220            return None
     221
    215222    def db_type(self, connection):
    216223        """
    217224        Returns the database column data type for this field, for the provided
    class Field(object):  
    232239        # mapped to one of the built-in Django field types. In this case, you
    233240        # can implement db_type() instead of get_internal_type() to specify
    234241        # exactly which wacky database column type you want to use.
    235         data = DictWrapper(self.__dict__, connection.ops.quote_name, "qn_")
    236         try:
    237             return (connection.creation.data_types[self.get_internal_type()]
    238                     % data)
    239         except KeyError:
    240             return None
     242        return self._internal_to_db_type(self.get_internal_type(), connection)
     243
     244    def rel_db_type(self, connection):
     245        """
     246        Returns the database column data type for related field referencing
     247        to this.
     248        """
     249        return self.db_type(connection)
    241250
    242251    @property
    243252    def unique(self):
    class AutoField(Field):  
    521530        'invalid': _("'%s' value must be an integer."),
    522531    }
    523532
    524     def __init__(self, *args, **kwargs):
     533    def __init__(self, verbose_name=None, name=None, big=False, **kwargs):
    525534        assert kwargs.get('primary_key', False) is True, \
    526535               "%ss must have primary_key=True." % self.__class__.__name__
    527536        kwargs['blank'] = True
    528         Field.__init__(self, *args, **kwargs)
     537        self.big = big
     538        Field.__init__(self, verbose_name, name, **kwargs)
    529539
    530540    def get_internal_type(self):
    531         return "AutoField"
     541        return 'AutoField' if not self.big else 'BigAutoField'
     542
     543    def rel_db_type(self, connection):
     544        db_type = 'IntegerField' if not self.big else 'BigIntegerField'
     545        return self._internal_to_db_type(db_type, connection)
    532546
    533547    def to_python(self, value):
    534548        if value is None:
    class PositiveIntegerField(IntegerField):  
    11421156    def get_internal_type(self):
    11431157        return "PositiveIntegerField"
    11441158
     1159    def rel_db_type(self, connection):
     1160        if connection.features.related_fields_match_type:
     1161            return self.db_type(connection)
     1162        return self._internal_to_db_type('IntegerField', connection)
     1163
    11451164    def formfield(self, **kwargs):
    11461165        defaults = {'min_value': 0}
    11471166        defaults.update(kwargs)
    class PositiveSmallIntegerField(IntegerField):  
    11531172    def get_internal_type(self):
    11541173        return "PositiveSmallIntegerField"
    11551174
     1175    def rel_db_type(self, connection):
     1176        if connection.features.related_fields_match_type:
     1177            return self.db_type(connection)
     1178        return self._internal_to_db_type('IntegerField', connection)
     1179
    11561180    def formfield(self, **kwargs):
    11571181        defaults = {'min_value': 0}
    11581182        defaults.update(kwargs)
  • django/db/models/fields/related.py

    diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
    index 08cc0a7..aa721ec 100644
    a b class ForeignKey(RelatedField, Field):  
    10431043        # If the database needs similar types for key fields however, the only
    10441044        # thing we can do is making AutoField an IntegerField.
    10451045        rel_field = self.rel.get_related_field()
    1046         if (isinstance(rel_field, AutoField) or
    1047                 (not connection.features.related_fields_match_type and
    1048                 isinstance(rel_field, (PositiveIntegerField,
    1049                                        PositiveSmallIntegerField)))):
    1050             return IntegerField().db_type(connection=connection)
    1051         return rel_field.db_type(connection=connection)
     1046
     1047        return rel_field.rel_db_type(connection=connection)
     1048
    10521049
    10531050class OneToOneField(ForeignKey):
    10541051    """
  • docs/ref/models/fields.txt

    diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt
    index 275c696..44b4eb4 100644
    a b Field types  
    320320``AutoField``
    321321-------------
    322322
    323 .. class:: AutoField(**options)
     323.. class:: AutoField([big=False, **options])
    324324
    325325An :class:`IntegerField` that automatically increments
    326326according to available IDs. You usually won't need to use this directly; a
    327327primary key field will automatically be added to your model if you don't specify
    328328otherwise. See :ref:`automatic-primary-key-fields`.
    329329
     330.. attribute:: AutoField.big
     331
     332    .. versionadded:: 1.5
     333
     334    Optional.  Either ``False`` or ``True``.  Default is ``False``. Allow you
     335    to use bigint for storing field values. This extends values range up to
     336    max 64 bit integer (from 1 to 9223372036854775807).
     337
     338
    330339``BigIntegerField``
    331340-------------------
    332341
  • new file tests/modeltests/bigautofield/models.py

    diff --git a/tests/modeltests/bigautofield/__init__.py b/tests/modeltests/bigautofield/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/modeltests/bigautofield/models.py b/tests/modeltests/bigautofield/models.py
    new file mode 100644
    index 0000000..95cf8c9
    - +  
     1# -*- coding: utf-8 -*-
     2from django.db import models
     3from django.utils.encoding import python_2_unicode_compatible
     4
     5
     6@python_2_unicode_compatible
     7class Village(models.Model):
     8    name = models.CharField(max_length=100)
     9
     10
     11@python_2_unicode_compatible
     12class Population(models.Model):
     13    village = models.ForeignKey(Village)
     14    total = models.IntegerField()
     15
     16
     17@python_2_unicode_compatible
     18class City(models.Model):
     19    id = models.AutoField(primary_key=True, big=True)
     20    name = models.CharField(max_length=100)
     21
     22
     23@python_2_unicode_compatible
     24class Weather(models.Model):
     25    city = models.ForeignKey(City)
     26    temp = models.IntegerField()
  • new file tests/modeltests/bigautofield/tests.py

    diff --git a/tests/modeltests/bigautofield/tests.py b/tests/modeltests/bigautofield/tests.py
    new file mode 100644
    index 0000000..2aa2f4b
    - +  
     1from __future__ import absolute_import, unicode_literals
     2
     3from django.db import connection
     4from django.test import TestCase, skipUnlessDBFeature
     5
     6from .models import Village, Population, City, Weather
     7
     8
     9class BigAutoFieldTest(TestCase):
     10
     11    def test_type(self):
     12        field = Village._meta.get_field_by_name('id')[0]
     13        self.assertEqual(field.get_internal_type(), 'AutoField')
     14        types = {
     15            'mysql': 'integer AUTO_INCREMENT', 'oracle': 'NUMBER(11)',
     16            'postgresql': 'serial', 'sqlite': 'integer',
     17        }
     18        self.assertEqual(field.db_type(connection), types[connection.vendor])
     19
     20        field = Population._meta.get_field_by_name('village')[0]
     21        types = {
     22            'mysql': 'integer', 'oracle': 'NUMBER(11)',
     23            'postgresql': 'integer', 'sqlite': 'integer',
     24        }
     25        self.assertEqual(field.db_type(connection), types[connection.vendor])
     26
     27    def test_big_type(self):
     28
     29        field = City._meta.get_field_by_name('id')[0]
     30        self.assertEqual(field.get_internal_type(), 'BigAutoField')
     31        types = {
     32            'mysql': 'bigint AUTO_INCREMENT', 'oracle': 'NUMBER(19)',
     33            'postgresql': 'bigserial', 'sqlite': 'integer',
     34        }
     35        self.assertEqual(field.db_type(connection), types[connection.vendor])
     36
     37        field = Weather._meta.get_field_by_name('city')[0]
     38        types = {
     39            'mysql': 'bigint', 'oracle': 'NUMBER(19)',
     40            'postgresql': 'bigint', 'sqlite': 'bigint',
     41        }
     42        self.assertEqual(field.db_type(connection), types[connection.vendor])
     43
     44    def test_usage(self):
     45        city_id = 8223372036854775807
     46        c = City.objects.create(id=city_id, name='Moscow')
     47        Weather.objects.create(city=c, temp=17)
     48
     49        c = City.objects.get(id=city_id)
     50        w = Weather.objects.get(city_id=city_id)
     51        self.assertEqual(c.id, city_id)
     52        self.assertEqual(w.city_id, city_id)
     53
     54        c.delete()
     55
     56        with self.assertRaises(Weather.DoesNotExist):
     57            Weather.objects.get(city_id=city_id)
Back to Top