Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid query when combining with ArrayField and NULL values #128

Open
sevdog opened this issue Jan 17, 2024 · 1 comment
Open

Invalid query when combining with ArrayField and NULL values #128

sevdog opened this issue Jan 17, 2024 · 1 comment

Comments

@sevdog
Copy link
Contributor

sevdog commented Jan 17, 2024

When combining a field from this library with ArrayField if any of the values in the array is None (or should be translated to NULL) an invalid query is generated causing an error like the following:

django.db.utils.DataError: invalid input syntax for type ...

In example, if using InetAddressField the generated SQL is something like

SELECT '{192.168.1.1,None}'::inet[]::inet[];

Using django built-in GenericIPAddressField instead produces the right query:

SELECT '{192.168.1.1,NULL}'::inet[]::inet[];
Here is a sample model with tests to ensure this behaviour:
# models.py
from django.contrib.postgres.fields import ArrayField
from django.db import models
from netfields import (CidrAddressField, InetAddressField, MACAddress8Field,
                       MACAddressField)


class ArrayModel(models.Model):
    ip_array = ArrayField(models.GenericIPAddressField(), null=True)
    inet_array = ArrayField(InetAddressField(), null=True)
    mac_array = ArrayField(MACAddressField(), null=True)
    mac8_array = ArrayField(MACAddress8Field(), null=True)
    cidr_array = ArrayField(CidrAddressField(), null=True)

# tests.py
from django.test import TestCase

from .models import ArrayModel


class NullsTestCase(TestCase):

    def test_ip(self):
        model = ArrayModel(ip_array=["192.168.1.1", None])
        model.save()

    def test_inet(self):
        model = ArrayModel(inet_array=["192.168.1.1", None])
        model.save()

    def test_mac(self):
        model = ArrayModel(mac_array=["FF:FF:FF:FF:FF:FF", None])
        model.save()

    def test_mac8(self):
        model = ArrayModel(mac8_array=["FF:FF:FF:FF:FF:FF", None])
        model.save()

    def test_cidr(self):
        model = ArrayModel(cidr_array=["192.168.1.0/24", None])
        model.save()

I have seen this issue using Django 4.2 and psycopg 3.1.17.

@sevdog
Copy link
Contributor Author

sevdog commented Jan 17, 2024

Looking into django code I see that GenericIPAddressField.get_db_prep_value internally calls connection.ops.adapt_ipaddressfield_value which behaves different from netfields:

https://github.com/django/django/blob/c7e986fc9f4848bd757d4b9b70a40586d2cee9fb/django/db/backends/postgresql/operations.py#L350-L353

Because if the value is falsy it just returns None and not Inet(None) (which is the result in netfields).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant