Opened 19 months ago
Closed 19 months ago
#35362 closed Bug (duplicate)
ArrayField with nested CharField with a max_length silently truncates overlong values
| Reported by: | Craig de Stigter | Owned by: | nobody |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | dev |
| Severity: | Normal | Keywords: | postgres |
| Cc: | Craig de Stigter | Triage Stage: | Accepted |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
With the following model
class TestModel(models.Model): arrayfield = ArrayField( models.CharField(max_length=63, blank=False), blank=False, null=False )
Saving an over-long string value into the arrayfield silently truncates the value:
>>> TestModel.objects.create(arrayfield=['a'*100]) <TestModel: TestModel object (1)> >>> len(TestModel.objects.get().arrayfield[0]) 63
This is probably because the ArrayField is casting its values (to varchar(63)[]) during queries for some reason. The postgres docs suggest that casting to varchar(X) will truncate strings to X length.
This seems related to #33647 although it's not quite the same situation since this isn't bulk_update
Change History (3)
comment:1 by , 19 months ago
| Keywords: | postgres added |
|---|---|
| Triage Stage: | Unreviewed → Accepted |
| Version: | 5.0 → dev |
comment:3 by , 19 months ago
| Resolution: | → duplicate |
|---|---|
| Status: | new → closed |
Duplicate of #33647.
Can see that ArrayField is also part of the ticket discussion.
Thank you for the report!
Confirmed behaviour on main, 5.0 and 4.2. Example failing test:
diff --git a/tests/postgres_tests/test_array.py b/tests/postgres_tests/test_array.py index 386a0afa3a..fc932ab19a 100644 --- a/tests/postgres_tests/test_array.py +++ b/tests/postgres_tests/test_array.py @@ -148,6 +148,11 @@ class TestSaveLoad(PostgreSQLTestCase): with self.assertRaises(IntegrityError): instance.save() + def test_char_max_length_exceeded(self): + instance = CharArrayModel(field=["a" * 11]) + with self.assertRaises(IntegrityError): + instance.save() + def test_nested(self): instance = NestedIntegerArrayModel(field=[[1, 2], [3, 4]]) instance.save()This generates the SQL which has the silent truncation
INSERT INTO "postgres_tests_chararraymodel" ("field") VALUES (\'{aaaaaaaaaaa}\'::varchar(10)[]) RETURNING "postgres_tests_chararraymodel"."id"