Skip to content

Commit

Permalink
Merge branch 'filter-input-conversion' into feature/icat-to-panosc-da…
Browse files Browse the repository at this point in the history
…ta-model-conversion-#265
  • Loading branch information
MRichards99 committed Jan 26, 2022
2 parents e52d595 + d7e2d81 commit 7f4cd96
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 19 deletions.
42 changes: 42 additions & 0 deletions datagateway_api/src/search_api/condition_setting_query.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from icat.query import Query


class ConditionSettingQuery(Query):
"""
Custom Query class to support the getting and setting of WHERE clauses outside of
the typical `Query.conditions` dict
"""

def __init__(
self,
client,
entity_name,
conditions=None,
aggregate=None,
includes=None,
str_conditions="",
):

super().__init__(
client,
entity_name,
conditions=conditions,
aggregate=aggregate,
includes=includes,
)
self.setConditionsByString(str_conditions)

def setConditionsByString(self, str_conditions): # noqa: N802
self._str_conditions = str_conditions

@property
def where_clause(self):
"""
Overriding Python ICAT's implementation to support the creation of WHERE clauses
within the search API
"""

if self._str_conditions:
return f"WHERE {self._str_conditions}"
else:
return super().where_clause
35 changes: 17 additions & 18 deletions datagateway_api/src/search_api/filters.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from copy import copy
from datetime import datetime
import logging

Expand Down Expand Up @@ -82,27 +83,25 @@ def __str__(self):
"""

if isinstance(self.search_api_query, SearchAPIQuery):
log.info("__str__ for SearchAPIWhereFilter, SearchAPIQuery found")
# Making a copy of the filter because `apply_filter()` can only be executed
# once per filter successfully
filter_copy = copy(self)

# Applying filter to the query so we get the correct JOINs, something not
# managed by the search API when we build the WHERE clause ourselves
self.apply_filter(self.search_api_query)
# Replicating the condition in Python ICAT format so it can be searched on
# the query and return as string representation
conds_dict = self.create_filter()
a, jpql_func = self.search_api_query.icat_query.query._split_db_functs(
self.field,
)
conds_dict[self.field] = self.search_api_query.icat_query.query._cond_value(
conds_dict[self.field], jpql_func,
)

str_conds = self.search_api_query.icat_query.query.search_conditions(
self.field, conds_dict,
)

try:
return str_conds[0]
except IndexError:
raise FilterError("Condition could not be found in Python ICAT query")
# Using a blank query to ensure the correct condition is retrieved from the
# where clause
blank_query = SearchAPIQuery(self.search_api_query.panosc_entity_name)
filter_copy.apply_filter(blank_query)
where_clause = blank_query.icat_query.query.where_clause
# The WHERE keyword is added by `ConditionSettingQuery`, where the
# `where_clause` property is overridden to support the search API building
# its own WHERE clauses to support `NestedWhereFilters`
str_cond = where_clause.replace("WHERE ", "")

return str_cond
else:
log.info(
"__str__ for SearchAPIWhereFilter, no query found so repr() will be"
Expand Down
39 changes: 38 additions & 1 deletion datagateway_api/src/search_api/query.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from datagateway_api.src.common.exceptions import SearchAPIError
from datagateway_api.src.datagateway_api.icat.query import ICATQuery
from datagateway_api.src.search_api.condition_setting_query import ConditionSettingQuery
from datagateway_api.src.search_api.panosc_mappings import mappings
from datagateway_api.src.search_api.session_handler import SessionHandler

Expand All @@ -10,10 +12,45 @@ def __init__(self, panosc_entity_name):
"base_icat_entity"
]

self.icat_query = ICATQuery(SessionHandler.client, self.icat_entity_name)
self.icat_query = SearchAPIICATQuery(
SessionHandler.client, self.icat_entity_name,
)

def __repr__(self):
return (
f"PaNOSC Entity Name: {self.panosc_entity_name}, ICAT Entity Name:"
f" {self.icat_entity_name}, ICAT Query: {str(self.icat_query.query)}"
)


class SearchAPIICATQuery(ICATQuery):
"""
Class which has identical functionality to `ICATQuery` but uses a different
`__init__` to call `ConditionSettingQuery` instead of the base `Query`. That class
contains features required for the search API
"""

def __init__(
self,
client,
entity_name,
conditions=None,
aggregate=None,
includes=None,
str_conditions=None,
):
try:
self.query = ConditionSettingQuery(
client,
entity_name,
conditions=conditions,
aggregate=aggregate,
includes=includes,
str_conditions=str_conditions,
)

self.query.manual_count = False
except ValueError as e:
raise SearchAPIError(
f"An issue has occurred while creating a query for ICAT: {e}",
)

0 comments on commit 7f4cd96

Please sign in to comment.