Coverage for src/fluree_py/types/query/where.py: 65%
23 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-02 03:03 +0000
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-02 03:03 +0000
1# You can think of a FlureeQL query executing in two phases: the where phase and the select phase. The where phase filters and returns sets of bound values that the select phase can use to construct JSON objects. The where clause may return node subject ?bindings that we then use with select expressions like "*" to perform graph crawls from those subject nodes.
2# The where clause may also retrieve all the bindings we need, and we simply instruct the select clause that we want those bindings returned directly as query results.
3# In any case, in addition to establishing logic variables for bound values, we use the where clause to establish various data constraints for the data we are interested in querying (e.g. filtering by a particular predicate value, or expressing optional and outer-join data conditions).
4# When a where clause is an array, it can combine a series of where conditions and where operations.
6# Define Condition as a dictionary with flexible key-value pairs
7from typing import Dict, List, Literal, TypeAlias, TypeGuard, Union
9from fluree_py.types.query.select import LogicVariable
11WhereResultSet: TypeAlias = Dict[str, str]
12WhereRelationship: TypeAlias = Dict[str, str]
14# A where condition describes relationships between nodes that must be satisfied for the nodes to be included in result sets, and it names those sets.
15#
16# Examples:
17# { "@id": "?s", "schema:name": "Sheil" }
18# { "@id": "?s", "schema:name": "?name" }
19# { "@id": "?s", "schema:name": "Freddie", "schema:familyName": "Mercury" }
20# { "@id": "http://example.org/jack", "?p": "?o" }
21WhereCondition = Union[WhereResultSet, WhereRelationship]
23# Examples:
24# [
25# {
26# "@id": "?s",
27# "bestFriend": "?friend"
28# },
29# {
30# "@id": "?friend",
31# "schema:name": "?name"
32# }
33# ]
34SuccessiveWhereCondition: TypeAlias = List[WhereCondition]
37# Examples:
38# [
39# "optional",
40# { "@id": "?s", "schema:name": "?name" },
41# { "@id": "?s", "schema:age": "?age" }
42# ]
43WhereOperationOptional: TypeAlias = List[Union[Literal["optional"], WhereCondition]]
46# Examples:
47# "(> ?age 45)"
48# "(< ?age 50)"
49# (! (strStarts ?url \"http\"))
50WhereFilterExpression: TypeAlias = str
53# A filter expression is a string that starts and ends with a parenthesis.
54# It starts with a function, followed by a space
55# It then contains a list of arguments.
56# Each argument may be a logic variable, a predicate, or a nested filter expression.
57# Examples:
58# "(> ?age 45)"
59# "(< ?age 50)"
60# (! (strStarts ?url \"http\"))
61def is_filter_expression(var: str) -> TypeGuard[WhereFilterExpression]:
62 """
63 Type guard to check if a string is a valid filter expression.
64 """
65 if not all(c.isprintable() for c in var):
66 return False
68 # Check if the string starts and ends with a parenthesis
69 if not (var.startswith("(") and var.endswith(")")):
70 return False
72 # Get internal string
73 internal = var[1:-1]
75 # Check if the internal string is balanced
76 if internal.count("(") != internal.count(")") or internal.count('"') % 2 != 0:
77 return False
79 # The internal string may have multiple arguments
80 # Each argument can be a nested filter expression, a logic variable, or a predicate
81 # There must be at least one logic variable or nested filter expression
83 return True
86# Examples:
87# ["filter", "(> ?age 45)", "(< ?age 50)"]
88WhereOperationFilter: TypeAlias = List[
89 Union[Literal["optional"], WhereFilterExpression]
90]
93# Examples:
94# [
95# "union",
96# { "@id": "?s", "schema:email": "?email" },
97# { "@id": "?s", "ex:email": "?email" }
98# ]
99WhereOperationUnion: TypeAlias = List[Union[Literal["union"], WhereCondition]]
101# Examples:
102# ["bind", "?canVote", "(>= ?age 18)"]
103WhereOperationBind: TypeAlias = List[
104 Union[Literal["bind"], LogicVariable, WhereFilterExpression]
105]
107WhereOperation = Union[
108 WhereOperationOptional,
109 WhereOperationFilter,
110 WhereOperationUnion,
111 WhereOperationBind,
112]
115WhereClauseEntry: TypeAlias = Union[WhereCondition, WhereOperation]
117WhereClause: TypeAlias = WhereClauseEntry | List[WhereClauseEntry]