#28291: ArrayField cannot contain JSONField; causes SQL error
----------------------------------+--------------------------------------
     Reporter:  Richard Eames     |                    Owner:  Zac Yauney
         Type:  Bug               |                   Status:  assigned
    Component:  contrib.postgres  |                  Version:  master
     Severity:  Normal            |               Resolution:
     Keywords:                    |             Triage Stage:  Accepted
    Has patch:  0                 |      Needs documentation:  0
  Needs tests:  0                 |  Patch needs improvement:  0
Easy pickings:  0                 |                    UI/UX:  0
----------------------------------+--------------------------------------
Changes (by David Hagen):

 * cc: David Hagen (added)


Comment:

 I did some investigation to figure out why this happens because it is kind
 of annoying to be unable to reuse `Field`s backed by `JsonField` in
 `ArrayField`s.

 The problem comes in the call to `psycopg2.extensions.cursor.execute(sql,
 params)` in `django.db.backends.utils.CursorWrapper._execute` (line 85 in
 Django 2.0). In this example, `execute` is called with `sql = ... VALUES
 (%s) ...` and `params = [[JsonAdaptor({"a": 1}), JsonAdaptor({"a": 1})]]`,
 where `JsonAdaptor` is `django.contrib.postgres.fields.JsonAdaptor` which
 is a thin wrapper around `psycopg2._json.Json`. Now, `execute` is C code
 in `psycopg2` which expands the SQL command to `... VALUES (ARRAY['{"a":
 1}', '{"b": 2}'])`. It gets those string representations of the JSON by
 calling `Json.getquoted`. If the field has type `jsonb` then the quoted
 string appears to be a perfectly valid value to insert into the table.
 However, if the field has type `jsonb[]`, then an array of quoted strings
 does not appear to be a valid value to insert, which is why the error is
 raised. The solution is to either cast the strings to `jsonb` or to cast
 the whole array to `jsonb[]` like this:
 {{{
 ... VALUES (ARRAY['{"a": 1}'::jsonb, '{"b": 2}'::jsonb]) ...
 ... VALUES (ARRAY['{"a": 1}', '{"b": 2}']::jsonb[]) ...
 }}}

 Whether the bug fundamentally lies with psycopg2 or django depends on
 whose duty it is to make sure the conversion to string properly casts to
 the right type, and I don't know that.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/28291#comment:4>
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/066.a7c597591926433b144722a7cd5e828c%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to