diff --git a/store/neurostore/resources/utils.py b/store/neurostore/resources/utils.py index 08974e35..2733a531 100644 --- a/store/neurostore/resources/utils.py +++ b/store/neurostore/resources/utils.py @@ -65,6 +65,9 @@ def validate_search_query(query: str) -> bool: if not validate_query_end(query): raise errors.SyntaxError("Query cannot end with an operator") + if not validate_multiple_operators(query): + raise errors.SyntaxError("Consecutive operators are not allowed") + return True @@ -98,6 +101,16 @@ def validate_query_end(query: str) -> bool: return True +def validate_multiple_operators(query: str) -> bool: + """Validate that there are no consecutive operators in a query.""" + operators = ("AND", "OR", "NOT", "&", "|", "&!") + query = query.strip().split(" ") + for i in range(len(query) - 1): + if query[i] in operators and query[i + 1] in operators: + return False + return True + + def count_chars(target, query: str) -> int: """Count the number of chars in a query string. Excluding those in quoted phrases.""" diff --git a/store/neurostore/tests/conftest.py b/store/neurostore/tests/conftest.py index 1189e214..b2762793 100644 --- a/store/neurostore/tests/conftest.py +++ b/store/neurostore/tests/conftest.py @@ -602,6 +602,9 @@ def simple_neurosynth_annotation(session, ingest_neurosynth): 'OR ("ASD")) AND (("decision*" OR "Dec', "Unmatched parentheses", ), + ( + 'smoking AND NOT memory', "Consecutive operators are not allowed" + ) ] valid_queries = [