#12818: sqlite3 backend should use single quotes for string values passed as args to django_date_trunc and django_extract ------------------------------------------+--------------------------------- Reporter: lakinwecker | Owner: nobody Status: new | Milestone: Component: Database layer (models, ORM) | Version: 1.1 Keywords: | Stage: Unreviewed Has_patch: 0 | ------------------------------------------+--------------------------------- Test case models.py: {{{ from django.db import models
#------------------------------------------------------------------------------ class SimpleModel(models.Model): month = models.PositiveIntegerField() some_date = models.DateTimeField() #------------------------------------------------------------------------------ class SecondModel(models.Model): year = models.PositiveIntegerField() some_date = models.DateTimeField() }}} Test case admin.py: {{{ from django.contrib import admin from datehierarchy.testbed.models import SimpleModel, SecondModel #------------------------------------------------------------------------------- class SimpleModelAdmin(admin.ModelAdmin): list_display = ('month', 'some_date',) date_hierarchy = 'some_date' admin.site.register(SimpleModel, SimpleModelAdmin) #------------------------------------------------------------------------------- class SecondModelAdmin(admin.ModelAdmin): list_display = ('year', 'some_date',) date_hierarchy = 'some_date' # Content Models admin.site.register(SecondModel, SecondModelAdmin) }}} Produces tracebacks like this even if valid dates are present: {{{ Traceback: File "/home/lakin/Desktop/django/core/handlers/base.py" in get_response 92. response = callback(request, *callback_args, **callback_kwargs) File "/home/lakin/Desktop/django/contrib/admin/options.py" in wrapper 226. return self.admin_site.admin_view(view)(*args, **kwargs) File "/home/lakin/Desktop/django/views/decorators/cache.py" in _wrapped_view_func 44. response = view_func(request, *args, **kwargs) File "/home/lakin/Desktop/django/contrib/admin/sites.py" in inner 186. return view(request, *args, **kwargs) File "/home/lakin/Desktop/django/contrib/admin/options.py" in changelist_view 986. ], context, context_instance=context_instance) File "/home/lakin/Desktop/django/shortcuts/__init__.py" in render_to_response 20. return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs) File "/home/lakin/Desktop/django/template/loader.py" in render_to_string 108. return t.render(context_instance) File "/home/lakin/Desktop/django/template/__init__.py" in render 178. return self.nodelist.render(context) File "/home/lakin/Desktop/django/template/__init__.py" in render 779. bits.append(self.render_node(node, context)) File "/home/lakin/Desktop/django/template/debug.py" in render_node 71. result = node.render(context) File "/home/lakin/Desktop/django/template/loader_tags.py" in render 97. return compiled_parent.render(context) File "/home/lakin/Desktop/django/template/__init__.py" in render 178. return self.nodelist.render(context) File "/home/lakin/Desktop/django/template/__init__.py" in render 779. bits.append(self.render_node(node, context)) File "/home/lakin/Desktop/django/template/debug.py" in render_node 71. result = node.render(context) File "/home/lakin/Desktop/django/template/loader_tags.py" in render 97. return compiled_parent.render(context) File "/home/lakin/Desktop/django/template/__init__.py" in render 178. return self.nodelist.render(context) File "/home/lakin/Desktop/django/template/__init__.py" in render 779. bits.append(self.render_node(node, context)) File "/home/lakin/Desktop/django/template/debug.py" in render_node 71. result = node.render(context) File "/home/lakin/Desktop/django/template/loader_tags.py" in render 24. result = self.nodelist.render(context) File "/home/lakin/Desktop/django/template/__init__.py" in render 779. bits.append(self.render_node(node, context)) File "/home/lakin/Desktop/django/template/debug.py" in render_node 71. result = node.render(context) File "/home/lakin/Desktop/django/template/loader_tags.py" in render 24. result = self.nodelist.render(context) File "/home/lakin/Desktop/django/template/__init__.py" in render 779. bits.append(self.render_node(node, context)) File "/home/lakin/Desktop/django/template/debug.py" in render_node 71. result = node.render(context) File "/home/lakin/Desktop/django/template/__init__.py" in render 936. dict = func(*args) File "/home/lakin/Desktop/django/contrib/admin/templatetags/admin_list.py" in date_hierarchy 313. } for year in years] File "/home/lakin/Desktop/django/db/models/query.py" in _result_iter 106. self._fill_cache() File "/home/lakin/Desktop/django/db/models/query.py" in _fill_cache 692. self._result_cache.append(self._iter.next()) File "/home/lakin/Desktop/django/db/models/sql/subqueries.py" in results_iter 397. date = typecast_timestamp(str(date)) File "/home/lakin/Desktop/django/db/backends/util.py" in typecast_timestamp 68. if not ' ' in s: return typecast_date(s) File "/home/lakin/Desktop/django/db/backends/util.py" in typecast_date 53. return s and datetime.date(*map(int, s.split('-'))) or None # returns None if s is null Exception Type: ValueError at /admin/testbed/secondmodel/ Exception Value: invalid literal for int() with base 10: 'None' }}} This is due to the use of double quotes in queries like the following: {{{ SELECT DISTINCT django_date_trunc('year', "testbed_secondmodel"."some_date") FROM "testbed_secondmodel" ORDER BY 1 ASC }}} Double quotes refer to column names, and int he above test case, the table testbed_secondmodel has a column named {{{year}}}, and as such the value of {{{year}}} is passed into the the python function {{{_sqlite_date_trunc}}} - instead of the string {{{"year"}}}. Instead, if one uses single quotes as per the string constant section in http://www.sqlite.org/lang_expr.html - it works just fine. Possible patch: {{{ Index: sqlite3/base.py =================================================================== --- sqlite3/base.py (revision 12398) +++ sqlite3/base.py (working copy) @@ -65,12 +65,12 @@ 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) + 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) + return 'django_date_trunc(\'%s\', %s)' % (lookup_type.lower(), field_name) def drop_foreignkey_sql(self): return "" }}} -- Ticket URL: <http://code.djangoproject.com/ticket/12818> Django <http://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To post to this group, send email to django-upda...@googlegroups.com. To unsubscribe from this group, send email to django-updates+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-updates?hl=en.