[Django] #29569: AutoField.cast_db_type returns the wrong 'type' for PostgrestSQL

31 views
Skip to first unread message

Django

unread,
Jul 16, 2018, 1:24:06 PM7/16/18
to django-...@googlegroups.com
#29569: AutoField.cast_db_type returns the wrong 'type' for PostgrestSQL
-------------------------------------+-------------------------------------
Reporter: Andrew | Owner: nobody
Standley |
Type: Bug | Status: new
Component: Database | Version: 2.0
layer (models, ORM) |
Severity: Normal | Keywords: cast
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
Using PostgreSQL 10.1 I encountered a problem trying to use `Cast` with an
`AutoField`. Trying to perform a manual join on generic foreign keys:
`Item.objects.filter(pk__in=Activity.objects.filter(content_type=item_ct).annotate(casted_pk=Cast('object_pk',
AutoField())).values('casted_pk'))`
The db connection responds with a "psycopg2.ProgrammingError: type
"serial" does not exist" error.

Upon investigation, it seems that `AutoField.cast_db_type` uses the
inherited definition from `Field` and returns `AutoField.db_type`.
However `AutoField.db_type` returns 'serial', which is a "syntactical
sugar" (not a true type) in Postgresql and only valid for creation.
The issue arises when `AutoField.cast_db_type` also returns 'serial',
which is invalid.

More confusingly `AutoField.rel_db_type` has already been overridden and
correctly returns 'integer'.

I believe fixing this is as easy as copying the override of
`AutoField.rel_db_type` to `AutoField.cast_db_type`.
I'll try to at least get this implemented as a test on my fork, so that it
is easy to confirm, but in the mean time the models to reproduce are:

{{{
class Item(models.Model):
label = models.CharField(max_length=100)
cost = models.IntegerField()

class Activity(models.Model):
content_type = models.ForeignKey(ContentType,
on_delete=models.CASCADE)
object_pk = models.CharField(max_length=100)
generic_object = GenericForeignKey(fk_field='object_pk')
}}}

Reference:
PostgreSQL docs on 'serial' type
(https://www.postgresql.org/docs/10/static/datatype-numeric.html#DATATYPE-
SERIAL)

--
Ticket URL: <https://code.djangoproject.com/ticket/29569>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Jul 16, 2018, 2:40:32 PM7/16/18
to django-...@googlegroups.com
#29569: Cast() to the AutoField generates invalid SQL.
-------------------------------------+-------------------------------------
Reporter: Andrew Standley | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: cast | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by felixxm):

* cc: felixxm (added)
* version: 2.0 => master
* easy: 0 => 1


Comment:

Thanks for the report. It doesn't sound natural to me to cast to
`AutoField`, because if you want to get an `integer` / `bigint`, why not
use it directly? Nevertheless you can use
`DatabaseOperations.cast_data_types` to fix this easily. This issue
probably appears on other back-ends.

--
Ticket URL: <https://code.djangoproject.com/ticket/29569#comment:1>

Django

unread,
Jul 16, 2018, 2:42:38 PM7/16/18
to django-...@googlegroups.com
#29569: Cast() to AutoField generates invalid SQL

-------------------------------------+-------------------------------------
Reporter: Andrew Standley | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: cast | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* stage: Unreviewed => Accepted


--
Ticket URL: <https://code.djangoproject.com/ticket/29569#comment:2>

Django

unread,
Jul 16, 2018, 3:40:20 PM7/16/18
to django-...@googlegroups.com
#29569: Cast() to AutoField generates invalid SQL
-------------------------------------+-------------------------------------
Reporter: Andrew Standley | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: cast | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Andrew Standley):

I'm using `Cast` on generic foreign keys to handle the type coercion in
the database, so I'm not coding around a 'known' field-type. I would
indeed just use an `IntegerField`, 'integer' type directly otherwise, and
as a temporary solution I'm doing just that for the edge case of
`AutoField`.

Can you elaborate on how I would use `DatabaseOperations.cast_data_types`
to fix this? I'm afraid I'm not familiar with that whole side of things.
It (perhaps naively) seems to me that `DatabaseOperations` is going to
have no effect on the `Cast` operation compilation as `Cast` selects the
`db_type` through a different route than the one that
`DatabaseOperations.cast_data_type` is used in.
Replying to [comment:1 felixxm]:


> Thanks for the report. It doesn't sound natural to me to cast to
`AutoField`, because if you want to get an `integer` / `bigint`, why not
use it directly? Nevertheless you can use
`DatabaseOperations.cast_data_types` to fix this easily. This issue
probably appears on other back-ends.

--
Ticket URL: <https://code.djangoproject.com/ticket/29569#comment:3>

Django

unread,
Jul 17, 2018, 3:59:02 AM7/17/18
to django-...@googlegroups.com
#29569: Cast() to AutoField generates invalid SQL
-------------------------------------+-------------------------------------
Reporter: Andrew Standley | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: cast | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by felixxm):

In Django we defined `DatabaseOperations` for each back-end.
`cast_db_type()` uses back-end specific dictionary
`connection.ops.cast_data_types` to find data type to use in the `Cast()`
(see
[https://github.com/django/django/blob/master/django/db/models/fields/__init__.py#L684-L689
django/db/models/fields/__init__.py]).

--
Ticket URL: <https://code.djangoproject.com/ticket/29569#comment:4>

Django

unread,
Jul 21, 2018, 7:37:05 AM7/21/18
to django-...@googlegroups.com
#29569: Cast() to AutoField generates invalid SQL
-------------------------------------+-------------------------------------
Reporter: Andrew Standley | Owner: felixxm
Type: Bug | Status: assigned

Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: cast | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by felixxm):

* status: new => assigned
* owner: nobody => felixxm
* has_patch: 0 => 1


Comment:

[https://github.com/django/django/pull/10210 PR]

--
Ticket URL: <https://code.djangoproject.com/ticket/29569#comment:5>

Django

unread,
Jul 21, 2018, 4:37:22 PM7/21/18
to django-...@googlegroups.com
#29569: Cast() to AutoField generates invalid SQL
-------------------------------------+-------------------------------------
Reporter: Andrew Standley | Owner: felixxm
Type: Bug | Status: assigned
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: cast | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* stage: Accepted => Ready for checkin


--
Ticket URL: <https://code.djangoproject.com/ticket/29569#comment:6>

Django

unread,
Jul 25, 2018, 2:00:45 AM7/25/18
to django-...@googlegroups.com
#29569: Cast() to AutoField generates invalid SQL
-------------------------------------+-------------------------------------
Reporter: Andrew Standley | Owner: felixxm
Type: Bug | Status: closed

Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution: fixed

Keywords: cast | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by GitHub <noreply@…>):

* status: assigned => closed
* resolution: => fixed


Comment:

In [changeset:"ac25dd1f8d48accc765c05aebb47c427e51f3255" ac25dd1f]:
{{{
#!CommitTicketReference repository=""
revision="ac25dd1f8d48accc765c05aebb47c427e51f3255"
Fixed #29569 -- Fixed Cast() with AutoField and BigAutoField.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/29569#comment:7>

Reply all
Reply to author
Forward
0 new messages