#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 django-updates+unsubscr...@googlegroups.com. To post to this group, send email to django-updates@googlegroups.com. 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.