Skip to content

Commit

Permalink
[#1776] Fix bug when upserting [] on JSON column in the datastore
Browse files Browse the repository at this point in the history
We were testing that the new value wasn't `None` using `if value`. As `[]` is a
falsy value, we never went through that `if` and ended up trying to run an
invalid SQL query.

This commit fixes that by explictly testing `if value is not None`.

This was first discovered in
http://stackoverflow.com/questions/24207065/inserting-empty-arrays-in-json-type-fields-in-datastore
  • Loading branch information
vitorbaptista authored and amercader committed Aug 1, 2014
1 parent f2bb082 commit 5793423
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 1 deletion.
2 changes: 1 addition & 1 deletion ckanext/datastore/db.py
Expand Up @@ -620,7 +620,7 @@ def upsert_data(context, data_dict):

for field in fields:
value = record.get(field['id'])
if value and field['type'].lower() == 'nested':
if value is not None and field['type'].lower() == 'nested':
## a tuple with an empty second value
record[field['id']] = (json.dumps(value), '')

Expand Down
29 changes: 29 additions & 0 deletions ckanext/datastore/tests/test_upsert.py
Expand Up @@ -13,6 +13,8 @@
import ckanext.datastore.db as db
from ckanext.datastore.tests.helpers import rebuild_all_dbs

assert_equal = nose.tools.assert_equal


class TestDatastoreUpsert(tests.WsgiAppCase):
sysadmin_user = None
Expand Down Expand Up @@ -236,6 +238,33 @@ def test_upsert_non_existing_field(self):

assert res_dict['success'] is False

def test_upsert_works_with_empty_list_in_json_field(self):
hhguide = u"hitchhiker's guide to the galaxy"

data = {
'resource_id': self.data['resource_id'],
'method': 'upsert',
'records': [{
'nested': [],
u'b\xfck': hhguide}]
}

postparams = '%s=1' % json.dumps(data)
auth = {'Authorization': str(self.sysadmin_user.apikey)}
res = self.app.post('/api/action/datastore_upsert', params=postparams,
extra_environ=auth)
res_dict = json.loads(res.body)
assert res_dict['success'] is True, res_dict

c = self.Session.connection()
results = c.execute('select * from "{0}"'.format(data['resource_id']))
record = [r for r in results.fetchall() if r[2] == hhguide]
self.Session.remove()
assert len(record) == 1, record
assert_equal(json.loads(record[0][4].json),
data['records'][0]['nested'])



class TestDatastoreInsert(tests.WsgiAppCase):
sysadmin_user = None
Expand Down

0 comments on commit 5793423

Please sign in to comment.