Skip to content

Commit

Permalink
[#2733] Add basic search (just processing filters and fields paramete…
Browse files Browse the repository at this point in the history
…rs).
  • Loading branch information
johnglover committed Jul 31, 2012
1 parent 50b636b commit 6857493
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 7 deletions.
53 changes: 47 additions & 6 deletions ckanext/datastore/db.py
Expand Up @@ -273,19 +273,18 @@ def insert_data(context, data_dict):
context['connection'].execute(sql_string, rows)


def delete_data(context, data_dict):
filters = data_dict.get('filters')
def _where_from_filters(field_ids, data_dict):
'Return a SQL WHERE clause from data_dict filters'
filters = data_dict.get('filters', {})

if not isinstance(filters, dict):
raise p.toolkit.ValidationError({
'filters': 'Not a json object'}
)

fields = _get_fields(context, data_dict)
field_ids = set([field['id'] for field in fields])

where_clauses = []
values = []

for field, value in filters.iteritems():
if field not in field_ids:
raise p.toolkit.ValidationError({
Expand All @@ -295,17 +294,59 @@ def delete_data(context, data_dict):
values.append(value)

where_clause = ' and '.join(where_clauses)
return where_clause, values


def delete_data(context, data_dict):
fields = _get_fields(context, data_dict)
field_ids = set([field['id'] for field in fields])
where_clause, where_values = _where_from_filters(field_ids, data_dict)

context['connection'].execute(
'delete from "{}" where {}'.format(
data_dict['resource_id'],
where_clause
),
values
where_values
)


def search_data(context, data_dict):
all_fields = _get_fields(context, data_dict)
all_field_ids = set([field['id'] for field in all_fields])

fields = data_dict.get('fields')

if fields:
check_fields(context, fields)
field_ids = set([field['id'] for field in fields])

for field in field_ids:
if not field in all_field_ids:
raise p.toolkit.ValidationError({
'fields': 'field "{}" not in table'.format(field)}
)
else:
fields = all_fields
field_ids = all_field_ids

select_columns = ', '.join(field_ids)

where_clause, where_values = _where_from_filters(all_field_ids, data_dict)

sql_string = 'select {} from "{}"'.format(
select_columns, data_dict['resource_id']
)

if where_clause:
sql_string += ' where {}'.format(where_clause)

results = context['connection'].execute(sql_string, where_values)

data_dict['total'] = results.rowcount
records = [(dict((f, r[f]) for f in field_ids)) for r in results]
data_dict['records'] = records

return data_dict


Expand Down
2 changes: 1 addition & 1 deletion ckanext/datastore/logic/action.py
Expand Up @@ -85,7 +85,7 @@ def datastore_search(context, data_dict):
:type offset: int
:param fields: ordered list of fields to return
(default: all fields in original order)
:type fields: list of strings
:type fields: list of dictionaries
:param sort: comma separated field names with ordering
eg: "fieldname1, fieldname2 desc"
:type sort: string
Expand Down
41 changes: 41 additions & 0 deletions ckanext/datastore/tests/test_datastore.py
Expand Up @@ -488,3 +488,44 @@ def test_search_basic(self):
extra_environ=auth)
res_dict = json.loads(res.body)
assert res_dict['success'] is True
result = res_dict['result']
assert result['total'] == len(self.data['records'])
assert result['records'] == self.data['records']

def test_search_invalid_field(self):
data = {'resource_id': self.data['resource_id'],
'fields': [{'id': 'bad'}]}
postparams = '%s=1' % json.dumps(data)
auth = {'Authorization': str(self.sysadmin_user.apikey)}
res = self.app.post('/api/action/datastore_search', params=postparams,
extra_environ=auth, status=409)
res_dict = json.loads(res.body)
assert res_dict['success'] is False

def test_search_fields(self):
data = {'resource_id': self.data['resource_id'],
'fields': [{'id': 'book'}]}
postparams = '%s=1' % json.dumps(data)
auth = {'Authorization': str(self.sysadmin_user.apikey)}
res = self.app.post('/api/action/datastore_search', params=postparams,
extra_environ=auth)
res_dict = json.loads(res.body)
assert res_dict['success'] is True
result = res_dict['result']
assert result['total'] == len(self.data['records'])
assert result['records'] == [{'book': 'annakarenina'},
{'book': 'warandpeace'}]

def test_search_filters(self):
data = {'resource_id': self.data['resource_id'],
'filters': {'book': 'annakarenina'}}
postparams = '%s=1' % json.dumps(data)
auth = {'Authorization': str(self.sysadmin_user.apikey)}
res = self.app.post('/api/action/datastore_search', params=postparams,
extra_environ=auth)
res_dict = json.loads(res.body)
assert res_dict['success'] is True
result = res_dict['result']
assert result['total'] == 1
assert result['records'] == [{'book': 'annakarenina',
'author': 'tolstoy'}]

0 comments on commit 6857493

Please sign in to comment.