#33647: bulk_update and bulk_create silently truncating values for size limited
fields on postgres
-------------------------------------+-------------------------------------
Reporter: jerch | Owner: Rowan
| Douglas
Type: Bug | Status: assigned
Component: Database layer | Version: 4.0
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Jacob Walls):
* severity: Release blocker => Normal
Old description:
> On postgres backend, `bulk_update` passes overlong values for size
> limited fields along without any notification/exception, instead
> truncating the value.
>
> Repro:
> {{{
> #!div style="font-size: 80%"
> Code highlighting:
> {{{#!python
> # some model to repro
> class TestModel(models.Model):
> name = models.CharField(max_length=32)
>
> # in the shell
> >>> from bulk_test.models import TestModel
> >>> tm=TestModel(name='hello')
> >>> tm.save()
> >>>
tm.name
> 'hello'
> >>>
tm.name='m'*100
> >>> tm.save() # good, raises:
> ...
> django.db.utils.DataError: value too long for type character
> varying(32)
>
> >>> TestModel.objects.all().values('name')
> <QuerySet [{'name': 'hello'}]>
> >>> TestModel.objects.all().update(name='z'*100) # good, raises as
> well:
> ...
> django.db.utils.DataError: value too long for type character
> varying(32)
>
> >>> TestModel.objects.all().values('name')
> <QuerySet [{'name': 'hello'}]>
> >>> TestModel.objects.bulk_update([tm], ['name']) # not raising,
> instead truncating:
> 1
> >>> TestModel.objects.all().values('name')
> <QuerySet [{'name': 'mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm'}]>
> }}}
> }}}
>
> Not sure, if this is intended/expected behavior, well it is inconsistent
> to `.save` or `.update`, which both raise here. I only tested postgres
> backend for this, it may apply to other size limiting databases as well
> (sqlite itself is not affected, as it does not limit values).
>
> If this is intended, it may be a good idea to at least document the
> slightly different behavior, so users are aware of it, and can prepare
> their code to avoid silent truncation with follow-up errors. A better way
> prolly would fix `bulk_update` to spot value overflows and raise, but I
> am not sure, if thats feasible.
New description:
EDIT: This issue originally only affected `bulk_update`, then started
affecting `bulk_create` in Django 5.2, but that aspect was fixed in Django
5.2.10 and Django 6.0.1.
Original report follows:
----
On postgres backend, `bulk_update` passes overlong values for size limited
fields along without any notification/exception, instead truncating the
value.
Repro:
{{{
#!div style="font-size: 80%"
Code highlighting:
{{{#!python
# some model to repro
class TestModel(models.Model):
name = models.CharField(max_length=32)
# in the shell
>>> from bulk_test.models import TestModel
>>> tm=TestModel(name='hello')
>>> tm.save()
>>>
tm.name
'hello'
>>>
tm.name='m'*100
>>> tm.save() # good, raises:
...
django.db.utils.DataError: value too long for type character varying(32)
>>> TestModel.objects.all().values('name')
<QuerySet [{'name': 'hello'}]>
>>> TestModel.objects.all().update(name='z'*100) # good, raises as
well:
...
django.db.utils.DataError: value too long for type character varying(32)
>>> TestModel.objects.all().values('name')
<QuerySet [{'name': 'hello'}]>
>>> TestModel.objects.bulk_update([tm], ['name']) # not raising,
instead truncating:
1
>>> TestModel.objects.all().values('name')
<QuerySet [{'name': 'mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm'}]>
}}}
}}}
Not sure, if this is intended/expected behavior, well it is inconsistent
to `.save` or `.update`, which both raise here. I only tested postgres
backend for this, it may apply to other size limiting databases as well
(sqlite itself is not affected, as it does not limit values).
If this is intended, it may be a good idea to at least document the
slightly different behavior, so users are aware of it, and can prepare
their code to avoid silent truncation with follow-up errors. A better way
prolly would fix `bulk_update` to spot value overflows and raise, but I am
not sure, if thats feasible.
--
Comment:
Downgrading from release blocker now that we've backported the fix to
`bulk_create()`. Only `bulk_update()` is still affected (as before).
Clarified the ticket description, but leaving both methods in the ticket
title so that the reference from the release notes is understandable.
--
Ticket URL: <
https://code.djangoproject.com/ticket/33647#comment:39>