Skip to content

Commit

Permalink
#238: Implement join specs on queries with one-to-many ordering
Browse files Browse the repository at this point in the history
- This feature is currently still in PR (therefore unreleased) so I haven't updated the dependency version, I will do so when Python ICAT is released for 0.19.0
  • Loading branch information
MRichards99 committed Jul 19, 2021
1 parent 369e38c commit cbef7b9
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 0 deletions.
1 change: 1 addition & 0 deletions datagateway_api/common/filter_order_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ def clear_python_icat_order_filters(self):
for icat_filter in self.filters
):
PythonICATOrderFilter.result_order = []
PythonICATOrderFilter.join_specs = {}

def manage_icat_filters(self, filters, query):
"""
Expand Down
30 changes: 30 additions & 0 deletions datagateway_api/common/icat/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ def apply_filter(self, query):
class PythonICATOrderFilter(OrderFilter):
# Used to append the order tuples across all filters in a single request
result_order = []
# When 1-many relationships occur, entities should be joined using a LEFT JOIN to
# prevent disappearing results when sorting on DataGateway's table view
join_specs = {}

def __init__(self, field, direction):
# Python ICAT doesn't automatically uppercase the direction, errors otherwise
Expand All @@ -165,6 +168,33 @@ def apply_filter(self, query):
# relationship
raise FilterError(e)

split_fields = self.field.split(".")
for field_pointer in range(len(split_fields)):
# Looking for plural entities but not field names
# This is to avoid adding JOINs to field names such as job's argument field
if (
split_fields[field_pointer].endswith("s")
and split_fields[field_pointer] != split_fields[-1]
):
# Length minus 1 is used to omit field names, same reason as above
for join_field_pointer in range(field_pointer, len(split_fields) - 1):
join_field_list = split_fields[
field_pointer : join_field_pointer + 1
]
join_field_str = ".".join(join_field_list)

PythonICATOrderFilter.join_specs[join_field_str] = "LEFT JOIN"

log.debug(
"Setting query join specs: %s", PythonICATOrderFilter.join_specs,
)
try:
query.setJoinSpecs(PythonICATOrderFilter.join_specs)
except (TypeError, ValueError) as e:
raise FilterError(e)

break


class PythonICATSkipFilter(SkipFilter):
def __init__(self, skip_value):
Expand Down

0 comments on commit cbef7b9

Please sign in to comment.