Opened 7 months ago

Last modified 6 months ago

#28767 new Bug

Incorrect value when annotating empty list as Value() on ArrayField.

Reported by: Matthew Schinckel Owned by:
Component: contrib.postgres Version: 1.11
Severity: Normal Keywords: annotate
Cc: Tomer Chachamu Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


I have a nice simple minimal case that shows this.

You can try this on any model: auth.User was just convenient for example. You'll need at least one object in there to query.

from django.contrib.auth.models import User
from django.contrib.postgres.fields import ArrayField
from django.db.models.expressions import Value
from django.db.models import IntegerField

User.objects.annotate(foo=Value([1], output_field=ArrayField(IntegerField()))).first().foo
# Outputs [1], as expected

User.objects.annotate(foo=Value([], output_field=ArrayField(IntegerField()))).first().foo
# Outputs '{}', which is _not_ correct.

Change History (4)

comment:1 Changed 7 months ago by Matthew Schinckel

Still a problem in current development head.

Last edited 7 months ago by Matthew Schinckel (previous) (diff)

comment:2 Changed 7 months ago by Tim Graham

Triage Stage: UnreviewedAccepted

#28762 may be related if not a duplicate.

comment:3 Changed 7 months ago by Tomer Chachamu

I added an (expected failing) test in #28762 for this.

I think this ticket will be easier to fix after #28762 . The problem is that psycopg2 adapts the empty list to '{}'. We cannot simply send ARRAY[] because this causes ERROR: cannot determine type of empty array. However we can send '{}'::integer[].

ArrayField.db_type() is already implemented and returns 'integer[]' so we can pass that value to ArrayLiteral and always output it into the SQL.

This might break something else, we'll see.

Last edited 7 months ago by Tomer Chachamu (previous) (diff)

comment:4 Changed 6 months ago by Tomer Chachamu

Cc: Tomer Chachamu added
Note: See TracTickets for help on using tickets.
Back to Top