Opened 6 years ago

Closed 6 years ago

#30044 closed Cleanup/optimization (fixed)

A FieldError should be raised when trying to update with F reference to MTI inherited field

Reported by: Tom Carrick Owned by: nobody
Component: Database layer (models, ORM) Version: dev
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

First, I'm not sure if it is or should be possible to do this, but I think at least the error message could be improved.

class Parent(models.Model):
    date_x = models.DateTimeField(blank=True, null=True)

class Child(Parent):
    date_y = models.DateTimeField(blank=True, null=True)


>>> Child.objects.update(date_y=F('date_x'))
Traceback (most recent call last):
  File "/Users/tom/.local/share/virtualenvs/test-PwakbHlc/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "/Users/tom/.local/share/virtualenvs/test-PwakbHlc/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 296, in execute
    return Database.Cursor.execute(self, query, params)
sqlite3.OperationalError: no such column: mtitest_parent.date_x

This error is confusing as it says it's looking at the parent model, but the field is right there on the parent model.

On another project using postgres, the error is better but it makes it seem like a bug in django (not sure if it is or isn't):

>>> Project.objects.update(deactivation_date=F('last_activity'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.5/site-packages/django/db/models/manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/local/lib/python3.5/site-packages/django/db/models/query.py", line 695, in update
    rows = query.get_compiler(self.db).execute_sql(CURSOR)
  File "/usr/local/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 1379, in execute_sql
    cursor = super().execute_sql(result_type)
  File "/usr/local/lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 1068, in execute_sql
    cursor.execute(sql, params)
  File "/usr/local/lib/python3.5/site-packages/django/db/backends/utils.py", line 100, in execute
    return super().execute(sql, params)
  File "/usr/local/lib/python3.5/site-packages/raven/contrib/django/client.py", line 123, in execute
    return real_execute(self, sql, params)
  File "/usr/local/lib/python3.5/site-packages/django/db/backends/utils.py", line 68, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/usr/local/lib/python3.5/site-packages/django/db/backends/utils.py", line 77, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/usr/local/lib/python3.5/site-packages/django/db/backends/utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python3.5/site-packages/django/db/utils.py", line 89, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/usr/local/lib/python3.5/site-packages/django/db/backends/utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: missing FROM-clause entry for table "content_contentmodel"
LINE 1: ...DATE "projects_project" SET "deactivation_date" = "content_c...
                                                             ^
missing FROM-clause entry for table "content_contentmodel"
LINE 1: ...DATE "projects_project" SET "deactivation_date" = "content_c...

I don't know if it's possible to fix this, but if not it would be nice if the user could be informed this isn't possible.

Change History (5)

comment:1 by Simon Charette, 6 years ago

This looks like #14104 (Allow joined field in F()s) in disguise because in the case of MTI F('date_x') actually translates to F('parent_ptr__date_x').

I assume you get a FieldError('Joined field references are not permitted in this query') error if you pass F('parent_ptr__date_x')?

If you do I assume we could keep this ticket opened as a cleanup to raise the same error on inherited fields since they require a join.

Adding support update() through joins is being revisited in #25643.

Version 1, edited 6 years ago by Simon Charette (previous) (next) (diff)

comment:2 by Tom Carrick, 6 years ago

Yeah, I think you're right. I already tried specifying the related field to the F() expression and got the error you described.

I guess that means the issue is mostly that the error doesn't tell the user anything useful (and seems straight up misleading in the sqlite example).

Also this limitation doesn't seem to be documented anywhere.

comment:3 by Simon Charette, 6 years ago

Summary: F expressions don't work with MTIA FieldError should be raised when trying to update with F reference to MTI inherited field
Triage Stage: UnreviewedAccepted
Type: BugCleanup/optimization
Version: 2.1master

Also this limitation doesn't seem to be documented anywhere.

We usually don't document bugs but since we explicitly error out in this case I guess we could include a mention in update() as well. Any thoughts on that Tim?

comment:4 by Simon Charette, 6 years ago

Has patch: set
Last edited 6 years ago by Tim Graham (previous) (diff)

comment:5 by Tim Graham <timograham@…>, 6 years ago

Resolution: fixed
Status: newclosed

In 9e5e5a65:

Fixed #30044 -- Raised a FieldError on inherited field update attempts.

Note: See TracTickets for help on using tickets.
Back to Top