Opened 17 years ago
Closed 13 years ago
#10015 closed Bug (fixed)
contrib.comments inline on Postgres 8.3 fails to cast integer to text
| Reported by: | Carl Meyer | Owned by: | Carl Meyer |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 1.4 |
| Severity: | Normal | Keywords: | postgresql, pk |
| Cc: | me@…, ramusus@…, tjurewicz@… | Triage Stage: | Accepted |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
(This bug is related to #8554 and #6523). If you display comments inline in the admin like so:
from django.contrib.contenttypes.generic import GenericTabularInline
class CarrotCommentInline(GenericTabularInline):
model = CarrotComment
ct_fk_field = 'object_pk'
extra = 0
fields = ('user', 'comment', 'ip_address', 'is_public', 'is_removed')
Postgres 8.3 will raise this error (for content object types with non-text primary keys):
Traceback (most recent call last):
File "/home/carljm/src/py/django/django-1.0.x/django/core/servers/basehttp.py", line 635, in __call__
return self.application(environ, start_response)
File "/home/carljm/src/py/django/django-1.0.x/django/core/handlers/wsgi.py", line 239, in __call__
response = self.get_response(request)
File "/home/carljm/src/py/django/django-1.0.x/django/core/handlers/base.py", line 128, in get_response
return self.handle_uncaught_exception(request, resolver, exc_info)
File "/home/carljm/src/py/django/django-1.0.x/django/core/handlers/base.py", line 148, in handle_uncaught_exception
return debug.technical_500_response(request, *exc_info)
File "/home/carljm/src/py/django/django-1.0.x/django/core/handlers/base.py", line 86, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "/home/carljm/src/py/django/django-1.0.x/django/contrib/admin/sites.py", line 157, in root
return self.model_page(request, *url.split('/', 2))
File "/home/carljm/src/py/django/django-1.0.x/django/views/decorators/cache.py", line 44, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File "/home/carljm/src/py/django/django-1.0.x/django/contrib/admin/sites.py", line 176, in model_page
return admin_obj(request, rest_of_url)
File "/home/carljm/src/py/django/django-1.0.x/django/contrib/admin/options.py", line 197, in __call__
return self.change_view(request, unquote(url))
File "/home/carljm/src/py/django/django-1.0.x/django/db/transaction.py", line 238, in _commit_on_success
res = func(*args, **kw)
File "/home/carljm/src/py/django/django-1.0.x/django/contrib/admin/options.py", line 592, in change_view
formset = FormSet(instance=obj)
File "/home/carljm/src/py/django/django-1.0.x/django/contrib/contenttypes/generic.py", line 303, in __init__
prefix=self.rel_name
File "/home/carljm/src/py/django/django-1.0.x/django/forms/models.py", line 350, in __init__
defaults['initial'] = [model_to_dict(obj) for obj in self.get_queryset()]
File "/home/carljm/src/py/django/django-1.0.x/django/db/models/query.py", line 185, in _result_iter
self._fill_cache()
File "/home/carljm/src/py/django/django-1.0.x/django/db/models/query.py", line 618, in _fill_cache
self._result_cache.append(self._iter.next())
File "/home/carljm/src/py/django/django-1.0.x/django/db/models/query.py", line 275, in iterator
for row in self.query.results_iter():
File "/home/carljm/src/py/django/django-1.0.x/django/db/models/sql/query.py", line 206, in results_iter
for rows in self.execute_sql(MULTI):
File "/home/carljm/src/py/django/django-1.0.x/django/db/models/sql/query.py", line 1734, in execute_sql
cursor.execute(sql, params)
File "/home/carljm/src/py/django/django-1.0.x/django/db/backends/util.py", line 19, in execute
return self.cursor.execute(sql, params)
ProgrammingError: operator does not exist: text = integer
LINE 1: ...HERE ("carrot_comments_carrotcomment"."object_pk" = 8 AND "...
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
This is because contrib.comments uses a text field type for the PK portion of its generic foreign key, and Postgres 8.3 does not automatically cast an integer to text.
This same core problem was already worked around once in [8641], which fixed #8554. This case is more difficult to work around, as the offending lookup is part of the BaseGenericInlineFormset code, and we can't just add an explicit cast there. Maybe the object_pk field type could be introspected to check if a cast is needed? Or perhaps there's a more appropriate general solution at the PostgreSQL db backend level.
Attachments (3)
Change History (19)
by , 17 years ago
| Attachment: | 10015_r9729.diff added |
|---|
comment:1 by , 17 years ago
| Has patch: | set |
|---|
I added a patch which fixes the case of a GFK with a ct_fk_field that is a TextField. This patch doesn't cover other possibilities (CharField?), though it could easily be extended to cover more.
comment:2 by , 17 years ago
| Component: | Contrib apps → django.contrib.comments |
|---|---|
| Keywords: | comments postgresql pk added |
| Triage Stage: | Unreviewed → Accepted |
Hah, yet another postgresql 8.3 quirk!!!
comment:3 by , 17 years ago
| Component: | django.contrib.comments → Contrib apps |
|---|---|
| Owner: | changed from to |
| Status: | new → assigned |
This is a contrib.contenttypes issue, not a contrib.comments issue, assuming GFK's are intended to support non-integer primary keys. If they are not, then there's only one possible fix in contrib.comments: switch to an IntegerField and don't support commenting on objects with non-integer PKs.
Accepting this, as I'm happy to improve the fix as needed until this is ready to go in.
comment:5 by , 17 years ago
| Cc: | added |
|---|
comment:6 by , 16 years ago
| Needs tests: | set |
|---|---|
| Patch needs improvement: | set |
comment:7 by , 16 years ago
| Cc: | added |
|---|
comment:8 by , 16 years ago
| Cc: | added |
|---|
comment:9 by , 16 years ago
Per discussion with Adrian at Chicago sprint, treating this as a database-level issue: SomeModel.objects.filter(name=3) (where name is a TextField or CharField) ought to just work across the board, but currently does not on Postgres 8.3+. The solution seems to be to give CharField and TextField a get_prep_value() method that forces conversion to a unicode string, as IntegerField does to int.
I'm attaching a patch with a test that currently fails on PG 8.3+, and the get_prep_value() fix. I also ran the full test suite several times with and without the patch to see if there's a noticeable performance impact from doing the isinstance check on every query to a CharField/TextField: there is not.
comment:10 by , 16 years ago
| Component: | Contrib apps → Database layer (models, ORM) |
|---|---|
| Keywords: | comments removed |
| Needs tests: | unset |
| Patch needs improvement: | unset |
comment:11 by , 16 years ago
| Resolution: | → fixed |
|---|---|
| Status: | assigned → closed |
comment:12 by , 16 years ago
comment:13 by , 16 years ago
| Resolution: | fixed |
|---|---|
| Status: | closed → reopened |
I just get similar error while try to delete object with comments as GenericRelationField:
class List(models.Model):
....
comments = generic.GenericRelation(Comment, object_id_field='object_pk')
Traceback or error:
Traceback:
File "/home/ram/workspace/movister/web_site/django/core/handlers/base.py" in get_response
96. response = middleware_method(request, callback, callback_args, callback_kwargs)
File "/home/ram/workspace/movister/web_site/firepython/middleware.py" in process_view
369. return self._profile_wrap(callback)(*args, **callback_kwargs)
File "/home/ram/workspace/movister/web_site/django/contrib/admin/options.py" in wrapper
243. return self.admin_site.admin_view(view)(*args, **kwargs)
File "/home/ram/workspace/movister/web_site/django/utils/decorators.py" in __call__
36. return self.decorator(self.func)(*args, **kwargs)
File "/home/ram/workspace/movister/web_site/django/utils/decorators.py" in _wrapped_view
86. response = view_func(request, *args, **kwargs)
File "/home/ram/workspace/movister/web_site/django/utils/decorators.py" in __call__
36. return self.decorator(self.func)(*args, **kwargs)
File "/home/ram/workspace/movister/web_site/django/views/decorators/cache.py" in _wrapped_view_func
70. response = view_func(request, *args, **kwargs)
File "/home/ram/workspace/movister/web_site/django/contrib/admin/sites.py" in inner
190. return view(request, *args, **kwargs)
File "/home/ram/workspace/movister/web_site/django/utils/decorators.py" in _wrapped_view
86. response = view_func(request, *args, **kwargs)
File "/home/ram/workspace/movister/web_site/django/contrib/admin/options.py" in delete_view
1123. obj.delete()
File "/home/ram/workspace/movister/web_site/django/db/models/base.py" in delete
604. delete_objects(seen_objs, using)
File "/home/ram/workspace/movister/web_site/django/db/models/query.py" in delete_objects
1192. del_query.delete_batch_related(pk_list, using=using)
File "/home/ram/workspace/movister/web_site/django/db/models/sql/subqueries.py" in delete_batch_related
65. self.do_query(f.m2m_db_table(), where, using=using)
File "/home/ram/workspace/movister/web_site/django/db/models/sql/subqueries.py" in do_query
27. self.get_compiler(using).execute_sql(None)
File "/home/ram/workspace/movister/web_site/django/db/models/sql/compiler.py" in execute_sql
674. cursor.execute(sql, params)
File "/home/ram/workspace/movister/web_site/debug_toolbar/panels/sql.py" in execute
90. return self.cursor.execute(sql, params)
Exception Type: ProgrammingError at /admin/movister/list/1/delete/
Exception Value: operator does not exist: text = integer
LINE 1: DELETE FROM "django_comments" WHERE ("object_pk" IN (1) AND ...
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
I use development trunk version r12267 of Django
comment:14 by , 16 years ago
| Resolution: | → fixed |
|---|---|
| Status: | reopened → closed |
The problem that was reported here is fixed. What you show is a not quite the same problem and deserves its own ticket, which is now #12721.
comment:15 by , 13 years ago
| Easy pickings: | unset |
|---|---|
| Has patch: | unset |
| Resolution: | fixed |
| Severity: | → Normal |
| Status: | closed → new |
| Type: | → Bug |
| UI/UX: | unset |
| Version: | 1.0 → 1.4 |
This error is still around!
Traceback (most recent call last):
File "/app/.heroku/src/django-tastypie/tastypie/resources.py", line 202, in wrapper
response = callback(request, *args, kwargs)
File "/app/.heroku/src/django-tastypie/tastypie/resources.py", line 441, in dispatch_list
return self.dispatch('list', request, kwargs)
File "/app/.heroku/src/django-tastypie/tastypie/resources.py", line 473, in dispatch
response = method(request, kwargs)
File "/app/.heroku/src/django-tastypie/tastypie/resources.py", line 1244, in get_list
to_be_serialized = paginator.page()
File "/app/.heroku/src/django-tastypie/tastypie/paginator.py", line 186, in page
count = self.get_count()
File "/app/.heroku/src/django-tastypie/tastypie/paginator.py", line 118, in get_count
return self.objects.count()
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/models/query.py", line 351, in count
return self.query.get_count(using=self.db)
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/models/sql/query.py", line 418, in get_count
number = obj.get_aggregation(using=using)[None]
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/models/sql/query.py", line 384, in get_aggregation
result = query.get_compiler(using).execute_sql(SINGLE)
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 818, in execute_sql
cursor.execute(sql, params)
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/backends/postgresql_psycopg2/base.py", line 52, in execute
return self.cursor.execute(query, args)
DatabaseError: operator does not exist: integer = text LINE 1: ... INNER JOIN "django_comments" ON ("pins_pin"."id" = "django_...
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
comment:16 by , 13 years ago
| Resolution: | → fixed |
|---|---|
| Status: | new → closed |
You've also reported this as #20271. Indeed, that's better than re-opening a ticket fixed years ago.
fix by introspection of ct_fk_field in BaseGenericInlineFormset