Opened 5 weeks ago

Closed 5 weeks ago

Last modified 5 weeks ago

#36107 closed Bug (fixed)

PostgresSQL ArrayField with size crashes with bulk_create

Reported by: Claude Paroz Owned by: Simon Charette
Component: Database layer (models, ORM) Version: 5.2
Severity: Release blocker Keywords:
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

When trying to bulk_create model instances with an ArrayField with a specified size (and triggering the UNNEST instruction), the query crashes at database level (column "<field>" is of type double precision[] but expression is of type double precision).

Probably a regression in a16eedcf9c69d8a11d94cac1811018c5b996d491

A possible reproducing test:

diff --git a/tests/postgres_tests/migrations/0002_create_test_models.py b/tests/postgres_tests/migrations/0002_create_test_models.py
index 188f79607d..31705ae21a 100644
--- a/tests/postgres_tests/migrations/0002_create_test_models.py
+++ b/tests/postgres_tests/migrations/0002_create_test_models.py
@@ -167,6 +167,28 @@ class Migration(migrations.Migration):
             },
             bases=(models.Model,),
         ),
+        migrations.CreateModel(
+            name="WithSizeArrayModel",
+            fields=[
+                (
+                    "id",
+                    models.AutoField(
+                        verbose_name="ID",
+                        serialize=False,
+                        auto_created=True,
+                        primary_key=True,
+                    ),
+                ),
+                (
+                    "field",
+                    ArrayField(models.FloatField(), size=2, null=True, blank=True),
+                ),
+            ],
+            options={
+                "required_db_vendor": "postgresql",
+            },
+            bases=(models.Model,),
+        ),
         migrations.CreateModel(
             name="NullableIntegerArrayModel",
             fields=[
diff --git a/tests/postgres_tests/models.py b/tests/postgres_tests/models.py
index e3118bc590..1563f6a35d 100644
--- a/tests/postgres_tests/models.py
+++ b/tests/postgres_tests/models.py
@@ -64,6 +64,10 @@ class DateTimeArrayModel(PostgreSQLModel):
     times = ArrayField(models.TimeField())
 
 
+class WithSizeArrayModel(PostgreSQLModel):
+    field = ArrayField(models.FloatField(), size=3)
+
+
 class NestedIntegerArrayModel(PostgreSQLModel):
     field = ArrayField(ArrayField(models.IntegerField()))
 
diff --git a/tests/postgres_tests/test_array.py b/tests/postgres_tests/test_array.py
index d930a01a1d..c2b0ebcd31 100644
--- a/tests/postgres_tests/test_array.py
+++ b/tests/postgres_tests/test_array.py
@@ -28,6 +28,7 @@ from .models import (
     OtherTypesArrayModel,
     PostgreSQLModel,
     Tag,
+    WithSizeArrayModel,
 )
 
 try:
@@ -216,6 +217,12 @@ class TestQuerying(PostgreSQLTestCase):
             ]
         )
 
+    def test_bulk_create_with_sized_arrayfield(self):
+        WithSizeArrayModel.objects.bulk_create([
+            WithSizeArrayModel(field=[1, 2]),
+            WithSizeArrayModel(field=[3, 4]),
+        ])
+
     def test_empty_list(self):
         NullableIntegerArrayModel.objects.create(field=[])
         obj = (

Change History (6)

comment:1 by Simon Charette, 5 weeks ago

Triage Stage: UnreviewedAccepted

Thanks Claude, I'll look at it shortly.

The current heuristics to disable the optimization when dealing with ArrayField didn't account for sized ones.

comment:2 by Simon Charette, 5 weeks ago

Owner: set to Simon Charette
Status: newassigned

comment:3 by Simon Charette, 5 weeks ago

Has patch: set

comment:4 by Claude Paroz, 5 weeks ago

Triage Stage: AcceptedReady for checkin

comment:5 by Sarah Boyce <42296566+sarahboyce@…>, 5 weeks ago

Resolution: fixed
Status: assignedclosed

In 22fc151b:

Fixed #36107 -- Adjusted UNNEST bulk_create strategy to opt-out sized arrays.

The array fields opt-out heuristic failed to account for sized arrays.

Note that we keep relying on db_type as opposed to performing an ArrayField
instance check against the column's field as there could be other
implementations of model fields that use Postgres arrays to store the
optimization must be disabled for all of them.

Refs #35936.

Thanks Claude Paroz for the report and test.

comment:6 by Sarah Boyce <42296566+sarahboyce@…>, 5 weeks ago

In ad6bca92:

[5.2.x] Fixed #36107 -- Adjusted UNNEST bulk_create strategy to opt-out sized arrays.

The array fields opt-out heuristic failed to account for sized arrays.

Note that we keep relying on db_type as opposed to performing an ArrayField
instance check against the column's field as there could be other
implementations of model fields that use Postgres arrays to store the
optimization must be disabled for all of them.

Refs #35936.

Thanks Claude Paroz for the report and test.

Backport of 22fc151bb86a553d84c62d7effd289356e9b6c6c from main.

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