Opened 4 weeks ago

Closed 4 weeks 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 Sarah Boyce, 4 weeks ago

Keywords: postgres added
Triage Stage: UnreviewedAccepted
Version: 5.0dev

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"

comment:2 by Mariusz Felisiak, 4 weeks ago

As for me this should be closed as a duplicate.

comment:3 by Sarah Boyce, 4 weeks ago

Resolution: duplicate
Status: newclosed

Duplicate of #33647.

Can see that ArrayField is also part of the ticket discussion.

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