From 2f45af6f58eaf30962b0cbc75b6bb79aaf8f347e Mon Sep 17 00:00:00 2001 From: Joseph Kocherhans Date: Wed, 24 Feb 2010 15:29:25 +0000 Subject: [PATCH] Fixed #12818. SQLite now properly quotes strings for date extraction and truncation. Thanks, SmilyChris. git-svn-id: http://code.djangoproject.com/svn/django/trunk@12573 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/backends/sqlite3/base.py | 12 ++++++--- tests/regressiontests/backends/models.py | 5 ++++ tests/regressiontests/backends/tests.py | 32 ++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py index a9b1aa3f8b..8ddb736d89 100644 --- a/django/db/backends/sqlite3/base.py +++ b/django/db/backends/sqlite3/base.py @@ -63,13 +63,17 @@ class DatabaseFeatures(BaseDatabaseFeatures): class DatabaseOperations(BaseDatabaseOperations): def date_extract_sql(self, lookup_type, field_name): # sqlite doesn't support extract, so we fake it with the user-defined - # function django_extract that's registered in connect(). - return 'django_extract("%s", %s)' % (lookup_type.lower(), field_name) + # function django_extract that's registered in connect(). Note that + # single quotes are used because this is a string (and could otherwise + # cause a collision with a field name). + return "django_extract('%s', %s)" % (lookup_type.lower(), field_name) def date_trunc_sql(self, lookup_type, field_name): # sqlite doesn't support DATE_TRUNC, so we fake it with a user-defined - # function django_date_trunc that's registered in connect(). - return 'django_date_trunc("%s", %s)' % (lookup_type.lower(), field_name) + # function django_date_trunc that's registered in connect(). Note that + # single quotes are used because this is a string (and could otherwise + # cause a collision with a field name). + return "django_date_trunc('%s', %s)" % (lookup_type.lower(), field_name) def drop_foreignkey_sql(self): return "" diff --git a/tests/regressiontests/backends/models.py b/tests/regressiontests/backends/models.py index 61b7b1af73..423bead1ad 100644 --- a/tests/regressiontests/backends/models.py +++ b/tests/regressiontests/backends/models.py @@ -15,6 +15,11 @@ class Person(models.Model): def __unicode__(self): return u'%s %s' % (self.first_name, self.last_name) +class SchoolClass(models.Model): + year = models.PositiveIntegerField() + day = models.CharField(max_length=9, blank=True) + last_updated = models.DateTimeField() + qn = connection.ops.quote_name __test__ = {'API_TESTS': """ diff --git a/tests/regressiontests/backends/tests.py b/tests/regressiontests/backends/tests.py index e4fa82403a..b31f35a44e 100644 --- a/tests/regressiontests/backends/tests.py +++ b/tests/regressiontests/backends/tests.py @@ -1,9 +1,12 @@ # -*- coding: utf-8 -*- # Unit and doctests for specific database backends. +import datetime +import models import unittest from django.db import backend, connection, DEFAULT_DB_ALIAS from django.db.backends.signals import connection_created from django.conf import settings +from django.test import TestCase class Callproc(unittest.TestCase): @@ -34,6 +37,35 @@ class LongString(unittest.TestCase): c.execute('DROP TABLE ltext') self.assertEquals(long_str, row[0].read()) +class DateQuotingTest(TestCase): + + def test_django_date_trunc(self): + """ + Test the custom ``django_date_trunc method``, in particular against + fields which clash with strings passed to it (e.g. 'year') - see + #12818__. + + __: http://code.djangoproject.com/ticket/12818 + + """ + updated = datetime.datetime(2010, 2, 20) + models.SchoolClass.objects.create(year=2009, last_updated=updated) + years = models.SchoolClass.objects.dates('last_updated', 'year') + self.assertEqual(list(years), [datetime.datetime(2010, 1, 1, 0, 0)]) + + def test_django_extract(self): + """ + Test the custom ``django_extract method``, in particular against fields + which clash with strings passed to it (e.g. 'day') - see #12818__. + + __: http://code.djangoproject.com/ticket/12818 + + """ + updated = datetime.datetime(2010, 2, 20) + models.SchoolClass.objects.create(year=2009, last_updated=updated) + classes = models.SchoolClass.objects.filter(last_updated__day=20) + self.assertEqual(len(classes), 1) + def connection_created_test(sender, **kwargs): print 'connection_created signal'