#27213: PostgreSQL-9.4 ArrayField with null throws ProgrammingError but not
ValidationError on Linux but not Windows
-------------------------------------+-------------------------------------
Reporter: mikofski | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.9
(models, ORM) | Keywords: postgres, arrayfield,
Severity: Normal | programmingerror
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Python-2.7.10
PostgreSQL-9.4
psycopg2-2.5.1 (linux) and psycopg2-2.6.1 (windows) (*)
Django-1.9
OS: Oracle7 vs. Windows 7
given a model:
{{{#!python
from django.contrib.postgres.fields import ArrayField
from django.db import models
class MyModel(models.Model):
my_array_field = ArrayField(base_field=models.FloatField(null=True))
}}}
If you try to save an array of `None` Django will validate it, but on
Linux PostgreSQL will not insert the row, but on windows it does.
{{{#!python
from my_app.models import MyModel
test_model = MyModel(my_array_field=[None]) # make a test instance of
model
test_model.full_clean() # check for ValidationError
# everything is okay!
test_model_full.save() # insert model instance into PostgreSQL database
# Windows: Success!
# Linux: Failure!
}}}
here is the stacktrace from Linux:
{{{
In [59]: rtest.save()
---------------------------------------------------------------------------
ProgrammingError Traceback (most recent call
last)
<ipython-input-59-34c0fed69116> in <module>()
----> 1 rtest.save()
~/.local/lib/python2.7/site-packages/django/db/models/base.pyc in
save(self, force_insert, force_update, using, update_fields)
706
707 self.save_base(using=using, force_insert=force_insert,
--> 708 force_update=force_update,
update_fields=update_fields)
709 save.alters_data = True
710
~/.local/lib/python2.7/site-packages/django/db/models/base.pyc in
save_base(self, raw, force_insert, force_update, using, update_fields)
734 if not raw:
735 self._save_parents(cls, using, update_fields)
--> 736 updated = self._save_table(raw, cls, force_insert,
force_update, using, update_fields)
737 # Store the database on which the object was saved
738 self._state.db = using
~/.local/lib/python2.7/site-packages/django/db/models/base.pyc in
_save_table(self, raw, cls, force_insert, force_update, using,
update_fields)
818
819 update_pk = bool(meta.has_auto_field and not pk_set)
--> 820 result = self._do_insert(cls._base_manager, using,
fields, update_pk, raw)
821 if update_pk:
822 setattr(self, meta.pk.attname, result)
~/.local/lib/python2.7/site-packages/django/db/models/base.pyc in
_do_insert(self, manager, using, fields, update_pk, raw)
857 """
858 return manager._insert([self], fields=fields,
return_id=update_pk,
--> 859 using=using, raw=raw)
860
861 def delete(self, using=None, keep_parents=False):
~/.local/lib/python2.7/site-packages/django/db/models/manager.pyc in
manager_method(self, *args, **kwargs)
120 def create_method(name, method):
121 def manager_method(self, *args, **kwargs):
--> 122 return getattr(self.get_queryset(), name)(*args,
**kwargs)
123 manager_method.__name__ = method.__name__
124 manager_method.__doc__ = method.__doc__
~/.local/lib/python2.7/site-packages/django/db/models/query.pyc in
_insert(self, objs, fields, return_id, raw, using)
1037 query = sql.InsertQuery(self.model)
1038 query.insert_values(fields, objs, raw=raw)
-> 1039 return
query.get_compiler(using=using).execute_sql(return_id)
1040 _insert.alters_data = True
1041 _insert.queryset_only = False
~/.local/lib/python2.7/site-packages/django/db/models/sql/compiler.pyc in
execute_sql(self, return_id)
1058 with self.connection.cursor() as cursor:
1059 for sql, params in self.as_sql():
-> 1060 cursor.execute(sql, params)
1061 if not (return_id and cursor):
1062 return
~/.local/lib/python2.7/site-packages/django/db/backends/utils.pyc in
execute(self, sql, params)
77 start = time()
78 try:
---> 79 return super(CursorDebugWrapper, self).execute(sql,
params)
80 finally:
81 stop = time()
~/.local/lib/python2.7/site-packages/django/db/backends/utils.pyc in
execute(self, sql, params)
62 return self.cursor.execute(sql)
63 else:
---> 64 return self.cursor.execute(sql, params)
65
66 def executemany(self, sql, param_list):
~/.local/lib/python2.7/site-packages/django/db/utils.pyc in __exit__(self,
exc_type, exc_value, traceback)
93 if dj_exc_type not in (DataError, IntegrityError):
94 self.wrapper.errors_occurred = True
---> 95 six.reraise(dj_exc_type, dj_exc_value, traceback)
96
97 def __call__(self, func):
~/.local/lib/python2.7/site-packages/django/db/backends/utils.pyc in
execute(self, sql, params)
62 return self.cursor.execute(sql)
63 else:
---> 64 return self.cursor.execute(sql, params)
65
66 def executemany(self, sql, param_list):
ProgrammingError: column "my_array_field" is of type double precision[]
but expression is of type text[]
LINE 1: ...ARRAY[NULL...
^
HINT: You will need to rewrite or cast the expression.
}}}
I wonder if it has anything to do with this SO question:
http://stackoverflow.com/questions/14713106/insert-unnested-array-of-null-
values-into-a-double-precision-column-postgresql
(*) if the issue is psycopg2 version discrepancy that's a bummer, because
I don't think I can build psycopg2 on a share without the postrgre dev
libs. :(
--
Ticket URL: <https://code.djangoproject.com/ticket/27213>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/051.1e8ac873a438f0ff1c94a028290094f9%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.