flowquery 1.0.18 → 1.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +3 -0
- package/.github/workflows/python-publish.yml +56 -4
- package/.github/workflows/release.yml +26 -19
- package/.husky/pre-commit +26 -0
- package/README.md +37 -32
- package/dist/flowquery.min.js +1 -1
- package/dist/graph/data.d.ts +5 -4
- package/dist/graph/data.d.ts.map +1 -1
- package/dist/graph/data.js +38 -20
- package/dist/graph/data.js.map +1 -1
- package/dist/graph/node.d.ts +2 -0
- package/dist/graph/node.d.ts.map +1 -1
- package/dist/graph/node.js +23 -0
- package/dist/graph/node.js.map +1 -1
- package/dist/graph/node_data.js +1 -1
- package/dist/graph/node_data.js.map +1 -1
- package/dist/graph/pattern.d.ts.map +1 -1
- package/dist/graph/pattern.js +11 -4
- package/dist/graph/pattern.js.map +1 -1
- package/dist/graph/relationship.d.ts +6 -1
- package/dist/graph/relationship.d.ts.map +1 -1
- package/dist/graph/relationship.js +43 -5
- package/dist/graph/relationship.js.map +1 -1
- package/dist/graph/relationship_data.d.ts +2 -0
- package/dist/graph/relationship_data.d.ts.map +1 -1
- package/dist/graph/relationship_data.js +8 -1
- package/dist/graph/relationship_data.js.map +1 -1
- package/dist/graph/relationship_match_collector.js +2 -2
- package/dist/graph/relationship_match_collector.js.map +1 -1
- package/dist/graph/relationship_reference.d.ts.map +1 -1
- package/dist/graph/relationship_reference.js +2 -1
- package/dist/graph/relationship_reference.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/parsing/parser.d.ts +6 -0
- package/dist/parsing/parser.d.ts.map +1 -1
- package/dist/parsing/parser.js +139 -72
- package/dist/parsing/parser.js.map +1 -1
- package/docs/flowquery.min.js +1 -1
- package/flowquery-py/misc/data/test.json +10 -0
- package/flowquery-py/misc/data/users.json +242 -0
- package/flowquery-py/notebooks/TestFlowQuery.ipynb +440 -0
- package/flowquery-py/pyproject.toml +48 -2
- package/flowquery-py/src/__init__.py +7 -5
- package/flowquery-py/src/compute/runner.py +14 -10
- package/flowquery-py/src/extensibility.py +8 -8
- package/flowquery-py/src/graph/__init__.py +7 -7
- package/flowquery-py/src/graph/data.py +38 -20
- package/flowquery-py/src/graph/database.py +10 -20
- package/flowquery-py/src/graph/node.py +50 -19
- package/flowquery-py/src/graph/node_data.py +1 -1
- package/flowquery-py/src/graph/node_reference.py +10 -11
- package/flowquery-py/src/graph/pattern.py +27 -37
- package/flowquery-py/src/graph/pattern_expression.py +13 -11
- package/flowquery-py/src/graph/patterns.py +2 -2
- package/flowquery-py/src/graph/physical_node.py +4 -3
- package/flowquery-py/src/graph/physical_relationship.py +5 -5
- package/flowquery-py/src/graph/relationship.py +62 -14
- package/flowquery-py/src/graph/relationship_data.py +7 -2
- package/flowquery-py/src/graph/relationship_match_collector.py +15 -10
- package/flowquery-py/src/graph/relationship_reference.py +4 -4
- package/flowquery-py/src/io/command_line.py +13 -14
- package/flowquery-py/src/parsing/__init__.py +2 -2
- package/flowquery-py/src/parsing/alias_option.py +1 -1
- package/flowquery-py/src/parsing/ast_node.py +21 -20
- package/flowquery-py/src/parsing/base_parser.py +7 -7
- package/flowquery-py/src/parsing/components/__init__.py +3 -3
- package/flowquery-py/src/parsing/components/from_.py +3 -1
- package/flowquery-py/src/parsing/components/headers.py +2 -2
- package/flowquery-py/src/parsing/components/null.py +2 -2
- package/flowquery-py/src/parsing/context.py +7 -7
- package/flowquery-py/src/parsing/data_structures/associative_array.py +7 -7
- package/flowquery-py/src/parsing/data_structures/json_array.py +3 -3
- package/flowquery-py/src/parsing/data_structures/key_value_pair.py +4 -4
- package/flowquery-py/src/parsing/data_structures/lookup.py +2 -2
- package/flowquery-py/src/parsing/data_structures/range_lookup.py +2 -2
- package/flowquery-py/src/parsing/expressions/__init__.py +16 -16
- package/flowquery-py/src/parsing/expressions/expression.py +16 -13
- package/flowquery-py/src/parsing/expressions/expression_map.py +9 -9
- package/flowquery-py/src/parsing/expressions/f_string.py +3 -3
- package/flowquery-py/src/parsing/expressions/identifier.py +4 -3
- package/flowquery-py/src/parsing/expressions/number.py +3 -3
- package/flowquery-py/src/parsing/expressions/operator.py +16 -16
- package/flowquery-py/src/parsing/expressions/reference.py +3 -3
- package/flowquery-py/src/parsing/expressions/string.py +2 -2
- package/flowquery-py/src/parsing/functions/__init__.py +17 -17
- package/flowquery-py/src/parsing/functions/aggregate_function.py +8 -8
- package/flowquery-py/src/parsing/functions/async_function.py +12 -9
- package/flowquery-py/src/parsing/functions/avg.py +4 -4
- package/flowquery-py/src/parsing/functions/collect.py +6 -6
- package/flowquery-py/src/parsing/functions/function.py +6 -6
- package/flowquery-py/src/parsing/functions/function_factory.py +31 -34
- package/flowquery-py/src/parsing/functions/function_metadata.py +10 -11
- package/flowquery-py/src/parsing/functions/functions.py +14 -6
- package/flowquery-py/src/parsing/functions/join.py +3 -3
- package/flowquery-py/src/parsing/functions/keys.py +3 -3
- package/flowquery-py/src/parsing/functions/predicate_function.py +8 -7
- package/flowquery-py/src/parsing/functions/predicate_sum.py +12 -7
- package/flowquery-py/src/parsing/functions/rand.py +2 -2
- package/flowquery-py/src/parsing/functions/range_.py +9 -4
- package/flowquery-py/src/parsing/functions/replace.py +2 -2
- package/flowquery-py/src/parsing/functions/round_.py +2 -2
- package/flowquery-py/src/parsing/functions/size.py +2 -2
- package/flowquery-py/src/parsing/functions/split.py +9 -4
- package/flowquery-py/src/parsing/functions/stringify.py +3 -3
- package/flowquery-py/src/parsing/functions/sum.py +4 -4
- package/flowquery-py/src/parsing/functions/to_json.py +2 -2
- package/flowquery-py/src/parsing/functions/type_.py +3 -3
- package/flowquery-py/src/parsing/functions/value_holder.py +1 -1
- package/flowquery-py/src/parsing/logic/__init__.py +2 -2
- package/flowquery-py/src/parsing/logic/case.py +0 -1
- package/flowquery-py/src/parsing/logic/when.py +3 -1
- package/flowquery-py/src/parsing/operations/__init__.py +10 -10
- package/flowquery-py/src/parsing/operations/aggregated_return.py +3 -5
- package/flowquery-py/src/parsing/operations/aggregated_with.py +4 -4
- package/flowquery-py/src/parsing/operations/call.py +6 -7
- package/flowquery-py/src/parsing/operations/create_node.py +5 -4
- package/flowquery-py/src/parsing/operations/create_relationship.py +5 -4
- package/flowquery-py/src/parsing/operations/group_by.py +18 -16
- package/flowquery-py/src/parsing/operations/load.py +21 -19
- package/flowquery-py/src/parsing/operations/match.py +8 -7
- package/flowquery-py/src/parsing/operations/operation.py +3 -3
- package/flowquery-py/src/parsing/operations/projection.py +6 -6
- package/flowquery-py/src/parsing/operations/return_op.py +9 -5
- package/flowquery-py/src/parsing/operations/unwind.py +3 -2
- package/flowquery-py/src/parsing/operations/where.py +9 -7
- package/flowquery-py/src/parsing/operations/with_op.py +2 -2
- package/flowquery-py/src/parsing/parser.py +178 -114
- package/flowquery-py/src/parsing/token_to_node.py +2 -2
- package/flowquery-py/src/tokenization/__init__.py +4 -4
- package/flowquery-py/src/tokenization/keyword.py +1 -1
- package/flowquery-py/src/tokenization/operator.py +1 -1
- package/flowquery-py/src/tokenization/string_walker.py +4 -4
- package/flowquery-py/src/tokenization/symbol.py +1 -1
- package/flowquery-py/src/tokenization/token.py +11 -11
- package/flowquery-py/src/tokenization/token_mapper.py +10 -9
- package/flowquery-py/src/tokenization/token_type.py +1 -1
- package/flowquery-py/src/tokenization/tokenizer.py +19 -19
- package/flowquery-py/src/tokenization/trie.py +18 -17
- package/flowquery-py/src/utils/__init__.py +1 -1
- package/flowquery-py/src/utils/object_utils.py +3 -3
- package/flowquery-py/src/utils/string_utils.py +12 -12
- package/flowquery-py/tests/compute/test_runner.py +214 -7
- package/flowquery-py/tests/parsing/test_parser.py +41 -0
- package/flowquery-vscode/flowQueryEngine/flowquery.min.js +1 -1
- package/package.json +1 -1
- package/src/graph/data.ts +38 -20
- package/src/graph/node.ts +23 -0
- package/src/graph/node_data.ts +1 -1
- package/src/graph/pattern.ts +13 -4
- package/src/graph/relationship.ts +45 -5
- package/src/graph/relationship_data.ts +8 -1
- package/src/graph/relationship_match_collector.ts +1 -1
- package/src/graph/relationship_reference.ts +2 -1
- package/src/index.ts +5 -5
- package/src/parsing/parser.ts +139 -71
- package/tests/compute/runner.test.ts +249 -79
- package/tests/parsing/parser.test.ts +32 -0
|
@@ -39,7 +39,7 @@ class Operator(ASTNode, ABC):
|
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
class Add(Operator):
|
|
42
|
-
def __init__(self):
|
|
42
|
+
def __init__(self) -> None:
|
|
43
43
|
super().__init__(1, True)
|
|
44
44
|
|
|
45
45
|
def value(self) -> Any:
|
|
@@ -47,7 +47,7 @@ class Add(Operator):
|
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
class Subtract(Operator):
|
|
50
|
-
def __init__(self):
|
|
50
|
+
def __init__(self) -> None:
|
|
51
51
|
super().__init__(1, True)
|
|
52
52
|
|
|
53
53
|
def value(self) -> Any:
|
|
@@ -55,7 +55,7 @@ class Subtract(Operator):
|
|
|
55
55
|
|
|
56
56
|
|
|
57
57
|
class Multiply(Operator):
|
|
58
|
-
def __init__(self):
|
|
58
|
+
def __init__(self) -> None:
|
|
59
59
|
super().__init__(2, True)
|
|
60
60
|
|
|
61
61
|
def value(self) -> Any:
|
|
@@ -63,7 +63,7 @@ class Multiply(Operator):
|
|
|
63
63
|
|
|
64
64
|
|
|
65
65
|
class Divide(Operator):
|
|
66
|
-
def __init__(self):
|
|
66
|
+
def __init__(self) -> None:
|
|
67
67
|
super().__init__(2, True)
|
|
68
68
|
|
|
69
69
|
def value(self) -> Any:
|
|
@@ -71,7 +71,7 @@ class Divide(Operator):
|
|
|
71
71
|
|
|
72
72
|
|
|
73
73
|
class Modulo(Operator):
|
|
74
|
-
def __init__(self):
|
|
74
|
+
def __init__(self) -> None:
|
|
75
75
|
super().__init__(2, True)
|
|
76
76
|
|
|
77
77
|
def value(self) -> Any:
|
|
@@ -79,7 +79,7 @@ class Modulo(Operator):
|
|
|
79
79
|
|
|
80
80
|
|
|
81
81
|
class Power(Operator):
|
|
82
|
-
def __init__(self):
|
|
82
|
+
def __init__(self) -> None:
|
|
83
83
|
super().__init__(3, False)
|
|
84
84
|
|
|
85
85
|
def value(self) -> Any:
|
|
@@ -87,7 +87,7 @@ class Power(Operator):
|
|
|
87
87
|
|
|
88
88
|
|
|
89
89
|
class Equals(Operator):
|
|
90
|
-
def __init__(self):
|
|
90
|
+
def __init__(self) -> None:
|
|
91
91
|
super().__init__(0, True)
|
|
92
92
|
|
|
93
93
|
def value(self) -> int:
|
|
@@ -95,7 +95,7 @@ class Equals(Operator):
|
|
|
95
95
|
|
|
96
96
|
|
|
97
97
|
class NotEquals(Operator):
|
|
98
|
-
def __init__(self):
|
|
98
|
+
def __init__(self) -> None:
|
|
99
99
|
super().__init__(0, True)
|
|
100
100
|
|
|
101
101
|
def value(self) -> int:
|
|
@@ -103,7 +103,7 @@ class NotEquals(Operator):
|
|
|
103
103
|
|
|
104
104
|
|
|
105
105
|
class GreaterThan(Operator):
|
|
106
|
-
def __init__(self):
|
|
106
|
+
def __init__(self) -> None:
|
|
107
107
|
super().__init__(0, True)
|
|
108
108
|
|
|
109
109
|
def value(self) -> int:
|
|
@@ -111,7 +111,7 @@ class GreaterThan(Operator):
|
|
|
111
111
|
|
|
112
112
|
|
|
113
113
|
class LessThan(Operator):
|
|
114
|
-
def __init__(self):
|
|
114
|
+
def __init__(self) -> None:
|
|
115
115
|
super().__init__(0, True)
|
|
116
116
|
|
|
117
117
|
def value(self) -> int:
|
|
@@ -119,7 +119,7 @@ class LessThan(Operator):
|
|
|
119
119
|
|
|
120
120
|
|
|
121
121
|
class GreaterThanOrEqual(Operator):
|
|
122
|
-
def __init__(self):
|
|
122
|
+
def __init__(self) -> None:
|
|
123
123
|
super().__init__(0, True)
|
|
124
124
|
|
|
125
125
|
def value(self) -> int:
|
|
@@ -127,7 +127,7 @@ class GreaterThanOrEqual(Operator):
|
|
|
127
127
|
|
|
128
128
|
|
|
129
129
|
class LessThanOrEqual(Operator):
|
|
130
|
-
def __init__(self):
|
|
130
|
+
def __init__(self) -> None:
|
|
131
131
|
super().__init__(0, True)
|
|
132
132
|
|
|
133
133
|
def value(self) -> int:
|
|
@@ -135,7 +135,7 @@ class LessThanOrEqual(Operator):
|
|
|
135
135
|
|
|
136
136
|
|
|
137
137
|
class And(Operator):
|
|
138
|
-
def __init__(self):
|
|
138
|
+
def __init__(self) -> None:
|
|
139
139
|
super().__init__(-1, True)
|
|
140
140
|
|
|
141
141
|
def value(self) -> int:
|
|
@@ -143,7 +143,7 @@ class And(Operator):
|
|
|
143
143
|
|
|
144
144
|
|
|
145
145
|
class Or(Operator):
|
|
146
|
-
def __init__(self):
|
|
146
|
+
def __init__(self) -> None:
|
|
147
147
|
super().__init__(-1, True)
|
|
148
148
|
|
|
149
149
|
def value(self) -> int:
|
|
@@ -151,7 +151,7 @@ class Or(Operator):
|
|
|
151
151
|
|
|
152
152
|
|
|
153
153
|
class Not(Operator):
|
|
154
|
-
def __init__(self):
|
|
154
|
+
def __init__(self) -> None:
|
|
155
155
|
super().__init__(0, True)
|
|
156
156
|
|
|
157
157
|
def is_operator(self) -> bool:
|
|
@@ -162,7 +162,7 @@ class Not(Operator):
|
|
|
162
162
|
|
|
163
163
|
|
|
164
164
|
class Is(Operator):
|
|
165
|
-
def __init__(self):
|
|
165
|
+
def __init__(self) -> None:
|
|
166
166
|
super().__init__(-1, True)
|
|
167
167
|
|
|
168
168
|
def value(self) -> int:
|
|
@@ -8,9 +8,9 @@ from .identifier import Identifier
|
|
|
8
8
|
|
|
9
9
|
class Reference(Identifier):
|
|
10
10
|
"""Represents a reference to a previously defined variable or expression.
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
References point to values defined earlier in the query (e.g., in WITH or LOAD statements).
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
Example:
|
|
15
15
|
ref = Reference("myVar", previous_node)
|
|
16
16
|
print(ref.value()) # Gets value from referred node
|
|
@@ -18,7 +18,7 @@ class Reference(Identifier):
|
|
|
18
18
|
|
|
19
19
|
def __init__(self, value: str, referred: Optional[ASTNode] = None):
|
|
20
20
|
"""Creates a new Reference to a variable.
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
Args:
|
|
23
23
|
value: The identifier name
|
|
24
24
|
referred: The node this reference points to (optional)
|
|
@@ -5,7 +5,7 @@ from ..ast_node import ASTNode
|
|
|
5
5
|
|
|
6
6
|
class String(ASTNode):
|
|
7
7
|
"""Represents a string literal in the AST.
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
Example:
|
|
10
10
|
s = String("hello")
|
|
11
11
|
print(s.value()) # "hello"
|
|
@@ -13,7 +13,7 @@ class String(ASTNode):
|
|
|
13
13
|
|
|
14
14
|
def __init__(self, value: str):
|
|
15
15
|
"""Creates a new String node with the given value.
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
Args:
|
|
18
18
|
value: The string value
|
|
19
19
|
"""
|
|
@@ -1,41 +1,41 @@
|
|
|
1
1
|
"""Functions module for FlowQuery parsing."""
|
|
2
2
|
|
|
3
|
-
from .function import Function
|
|
4
3
|
from .aggregate_function import AggregateFunction
|
|
5
4
|
from .async_function import AsyncFunction
|
|
6
|
-
from .
|
|
7
|
-
from .
|
|
8
|
-
from .
|
|
5
|
+
from .avg import Avg
|
|
6
|
+
from .collect import Collect
|
|
7
|
+
from .function import Function
|
|
8
|
+
from .function_factory import FunctionFactory
|
|
9
9
|
from .function_metadata import (
|
|
10
10
|
FunctionCategory,
|
|
11
|
-
ParameterSchema,
|
|
12
|
-
OutputSchema,
|
|
13
|
-
FunctionMetadata,
|
|
14
11
|
FunctionDef,
|
|
15
12
|
FunctionDefOptions,
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
FunctionMetadata,
|
|
14
|
+
OutputSchema,
|
|
15
|
+
ParameterSchema,
|
|
18
16
|
get_function_metadata,
|
|
17
|
+
get_registered_function_factory,
|
|
18
|
+
get_registered_function_metadata,
|
|
19
19
|
)
|
|
20
|
-
from .
|
|
21
|
-
|
|
22
|
-
# Built-in functions
|
|
23
|
-
from .sum import Sum
|
|
24
|
-
from .avg import Avg
|
|
25
|
-
from .collect import Collect
|
|
20
|
+
from .functions import Functions
|
|
26
21
|
from .join import Join
|
|
27
22
|
from .keys import Keys
|
|
23
|
+
from .predicate_function import PredicateFunction
|
|
24
|
+
from .predicate_sum import PredicateSum
|
|
28
25
|
from .rand import Rand
|
|
29
26
|
from .range_ import Range
|
|
27
|
+
from .reducer_element import ReducerElement
|
|
30
28
|
from .replace import Replace
|
|
31
29
|
from .round_ import Round
|
|
32
30
|
from .size import Size
|
|
33
31
|
from .split import Split
|
|
34
32
|
from .stringify import Stringify
|
|
33
|
+
|
|
34
|
+
# Built-in functions
|
|
35
|
+
from .sum import Sum
|
|
35
36
|
from .to_json import ToJson
|
|
36
37
|
from .type_ import Type
|
|
37
|
-
from .
|
|
38
|
-
from .predicate_sum import PredicateSum
|
|
38
|
+
from .value_holder import ValueHolder
|
|
39
39
|
|
|
40
40
|
__all__ = [
|
|
41
41
|
# Base classes
|
|
@@ -8,10 +8,10 @@ from .reducer_element import ReducerElement
|
|
|
8
8
|
|
|
9
9
|
class AggregateFunction(Function):
|
|
10
10
|
"""Base class for aggregate functions that reduce multiple values to a single value.
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
Aggregate functions like SUM, AVG, and COLLECT process multiple input values
|
|
13
13
|
and produce a single output. They cannot be nested within other aggregate functions.
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
Example:
|
|
16
16
|
sum_func = Sum()
|
|
17
17
|
# Used in: RETURN SUM(values)
|
|
@@ -19,19 +19,19 @@ class AggregateFunction(Function):
|
|
|
19
19
|
|
|
20
20
|
def __init__(self, name: Optional[str] = None):
|
|
21
21
|
"""Creates a new AggregateFunction with the given name.
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
Args:
|
|
24
24
|
name: The function name
|
|
25
25
|
"""
|
|
26
26
|
super().__init__(name)
|
|
27
27
|
self._overridden: Any = None
|
|
28
28
|
|
|
29
|
-
def reduce(self, value:
|
|
29
|
+
def reduce(self, value: Any) -> None:
|
|
30
30
|
"""Processes a value during the aggregation phase.
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
Args:
|
|
33
33
|
value: The element to aggregate
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
Raises:
|
|
36
36
|
NotImplementedError: If not implemented by subclass
|
|
37
37
|
"""
|
|
@@ -39,10 +39,10 @@ class AggregateFunction(Function):
|
|
|
39
39
|
|
|
40
40
|
def element(self) -> ReducerElement:
|
|
41
41
|
"""Creates a reducer element for this aggregate function.
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
Returns:
|
|
44
44
|
A ReducerElement instance
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
Raises:
|
|
47
47
|
NotImplementedError: If not implemented by subclass
|
|
48
48
|
"""
|
|
@@ -8,10 +8,10 @@ from .function import Function
|
|
|
8
8
|
|
|
9
9
|
class AsyncFunction(Function):
|
|
10
10
|
"""Represents an async data provider function call for use in LOAD operations.
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
This class holds the function name and arguments, and provides async iteration
|
|
13
13
|
over the results from a registered async data provider.
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
Example:
|
|
16
16
|
# Used in: LOAD JSON FROM myDataSource('arg1', 'arg2') AS data
|
|
17
17
|
async_func = AsyncFunction("myDataSource")
|
|
@@ -27,7 +27,7 @@ class AsyncFunction(Function):
|
|
|
27
27
|
@parameters.setter
|
|
28
28
|
def parameters(self, nodes: List[ASTNode]) -> None:
|
|
29
29
|
"""Sets the function parameters.
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
Args:
|
|
32
32
|
nodes: Array of AST nodes representing the function arguments
|
|
33
33
|
"""
|
|
@@ -36,7 +36,7 @@ class AsyncFunction(Function):
|
|
|
36
36
|
def get_arguments(self) -> List[Any]:
|
|
37
37
|
"""Evaluates all parameters and returns their values.
|
|
38
38
|
Used by the framework to pass arguments to generate().
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
Returns:
|
|
41
41
|
Array of parameter values
|
|
42
42
|
"""
|
|
@@ -44,19 +44,22 @@ class AsyncFunction(Function):
|
|
|
44
44
|
|
|
45
45
|
async def generate(self, *args: Any) -> AsyncGenerator[Any, None]:
|
|
46
46
|
"""Generates the async data provider function results.
|
|
47
|
-
|
|
47
|
+
|
|
48
48
|
Subclasses override this method with their own typed parameters.
|
|
49
49
|
The framework automatically evaluates the AST children and spreads
|
|
50
50
|
them as arguments when calling this method.
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
Args:
|
|
53
53
|
args: Arguments passed from the query (e.g., myFunc(arg1, arg2))
|
|
54
|
-
|
|
54
|
+
|
|
55
55
|
Yields:
|
|
56
56
|
Data items from the async provider
|
|
57
|
-
|
|
57
|
+
|
|
58
58
|
Raises:
|
|
59
59
|
NotImplementedError: If the function is not registered as an async provider
|
|
60
60
|
"""
|
|
61
61
|
raise NotImplementedError("generate method must be overridden in subclasses.")
|
|
62
|
-
|
|
62
|
+
# Note: yield is here only to make this a generator function
|
|
63
|
+
# It will never be reached due to the raise above
|
|
64
|
+
if False: # pragma: no cover
|
|
65
|
+
yield # Make this a generator
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
from typing import Optional
|
|
4
4
|
|
|
5
5
|
from .aggregate_function import AggregateFunction
|
|
6
|
-
from .reducer_element import ReducerElement
|
|
7
6
|
from .function_metadata import FunctionDef
|
|
7
|
+
from .reducer_element import ReducerElement
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class AvgReducerElement(ReducerElement):
|
|
11
11
|
"""Reducer element for Avg aggregate function."""
|
|
12
12
|
|
|
13
|
-
def __init__(self):
|
|
13
|
+
def __init__(self) -> None:
|
|
14
14
|
self._count: int = 0
|
|
15
15
|
self._sum: Optional[float] = None
|
|
16
16
|
|
|
@@ -40,11 +40,11 @@ class AvgReducerElement(ReducerElement):
|
|
|
40
40
|
})
|
|
41
41
|
class Avg(AggregateFunction):
|
|
42
42
|
"""Avg aggregate function.
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
Calculates the average of numeric values across grouped rows.
|
|
45
45
|
"""
|
|
46
46
|
|
|
47
|
-
def __init__(self):
|
|
47
|
+
def __init__(self) -> None:
|
|
48
48
|
super().__init__("avg")
|
|
49
49
|
self._expected_parameter_count = 1
|
|
50
50
|
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
"""Collect aggregate function."""
|
|
2
2
|
|
|
3
|
-
from typing import Any, Dict, List, Union
|
|
4
3
|
import json
|
|
4
|
+
from typing import Any, Dict, List, Union
|
|
5
5
|
|
|
6
6
|
from .aggregate_function import AggregateFunction
|
|
7
|
-
from .reducer_element import ReducerElement
|
|
8
7
|
from .function_metadata import FunctionDef
|
|
8
|
+
from .reducer_element import ReducerElement
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class CollectReducerElement(ReducerElement):
|
|
12
12
|
"""Reducer element for Collect aggregate function."""
|
|
13
13
|
|
|
14
|
-
def __init__(self):
|
|
14
|
+
def __init__(self) -> None:
|
|
15
15
|
self._value: List[Any] = []
|
|
16
16
|
|
|
17
17
|
@property
|
|
@@ -26,7 +26,7 @@ class CollectReducerElement(ReducerElement):
|
|
|
26
26
|
class DistinctCollectReducerElement(ReducerElement):
|
|
27
27
|
"""Reducer element for Collect aggregate function with DISTINCT."""
|
|
28
28
|
|
|
29
|
-
def __init__(self):
|
|
29
|
+
def __init__(self) -> None:
|
|
30
30
|
self._value: Dict[str, Any] = {}
|
|
31
31
|
|
|
32
32
|
@property
|
|
@@ -51,11 +51,11 @@ class DistinctCollectReducerElement(ReducerElement):
|
|
|
51
51
|
})
|
|
52
52
|
class Collect(AggregateFunction):
|
|
53
53
|
"""Collect aggregate function.
|
|
54
|
-
|
|
54
|
+
|
|
55
55
|
Collects values into an array across grouped rows.
|
|
56
56
|
"""
|
|
57
57
|
|
|
58
|
-
def __init__(self):
|
|
58
|
+
def __init__(self) -> None:
|
|
59
59
|
super().__init__("collect")
|
|
60
60
|
self._expected_parameter_count = 1
|
|
61
61
|
self._distinct: bool = False
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
"""Base class for all functions in FlowQuery."""
|
|
2
2
|
|
|
3
|
-
from typing import List, Optional
|
|
3
|
+
from typing import List, Optional
|
|
4
4
|
|
|
5
5
|
from ..ast_node import ASTNode
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class Function(ASTNode):
|
|
9
9
|
"""Base class for all functions in FlowQuery.
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
Functions can have parameters and may support the DISTINCT modifier.
|
|
12
12
|
Subclasses implement specific function logic.
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
Example:
|
|
15
15
|
func = FunctionFactory.create("sum")
|
|
16
16
|
func.parameters = [expression1, expression2]
|
|
@@ -18,7 +18,7 @@ class Function(ASTNode):
|
|
|
18
18
|
|
|
19
19
|
def __init__(self, name: Optional[str] = None):
|
|
20
20
|
"""Creates a new Function with the given name.
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
Args:
|
|
23
23
|
name: The function name
|
|
24
24
|
"""
|
|
@@ -35,10 +35,10 @@ class Function(ASTNode):
|
|
|
35
35
|
@parameters.setter
|
|
36
36
|
def parameters(self, nodes: List[ASTNode]) -> None:
|
|
37
37
|
"""Sets the function parameters.
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
Args:
|
|
40
40
|
nodes: Array of AST nodes representing the function arguments
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
Raises:
|
|
43
43
|
ValueError: If the number of parameters doesn't match expected count
|
|
44
44
|
"""
|
|
@@ -2,9 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
from typing import Any, Callable, Dict, List, Optional
|
|
4
4
|
|
|
5
|
-
from .function import Function
|
|
6
|
-
from .async_function import AsyncFunction
|
|
7
|
-
from .predicate_function import PredicateFunction
|
|
8
5
|
from .function_metadata import (
|
|
9
6
|
FunctionMetadata,
|
|
10
7
|
get_function_metadata,
|
|
@@ -15,23 +12,23 @@ from .function_metadata import (
|
|
|
15
12
|
|
|
16
13
|
class FunctionFactory:
|
|
17
14
|
"""Factory for creating function instances by name.
|
|
18
|
-
|
|
15
|
+
|
|
19
16
|
All functions are registered via the @FunctionDef decorator.
|
|
20
17
|
Maps function names (case-insensitive) to their corresponding implementation classes.
|
|
21
18
|
Supports built-in functions like sum, avg, collect, range, split, join, etc.
|
|
22
|
-
|
|
19
|
+
|
|
23
20
|
Example:
|
|
24
21
|
sum_func = FunctionFactory.create("sum")
|
|
25
22
|
avg_func = FunctionFactory.create("AVG")
|
|
26
23
|
"""
|
|
27
24
|
|
|
28
25
|
@staticmethod
|
|
29
|
-
def get_async_provider(name: str) -> Optional[Callable]:
|
|
26
|
+
def get_async_provider(name: str) -> Optional[Callable[..., Any]]:
|
|
30
27
|
"""Gets an async data provider by name.
|
|
31
|
-
|
|
28
|
+
|
|
32
29
|
Args:
|
|
33
30
|
name: The function name (case-insensitive)
|
|
34
|
-
|
|
31
|
+
|
|
35
32
|
Returns:
|
|
36
33
|
The async data provider, or None if not found
|
|
37
34
|
"""
|
|
@@ -40,10 +37,10 @@ class FunctionFactory:
|
|
|
40
37
|
@staticmethod
|
|
41
38
|
def is_async_provider(name: str) -> bool:
|
|
42
39
|
"""Checks if a function name is registered as an async data provider.
|
|
43
|
-
|
|
40
|
+
|
|
44
41
|
Args:
|
|
45
42
|
name: The function name (case-insensitive)
|
|
46
|
-
|
|
43
|
+
|
|
47
44
|
Returns:
|
|
48
45
|
True if the function is an async data provider
|
|
49
46
|
"""
|
|
@@ -52,10 +49,10 @@ class FunctionFactory:
|
|
|
52
49
|
@staticmethod
|
|
53
50
|
def get_metadata(name: str) -> Optional[FunctionMetadata]:
|
|
54
51
|
"""Gets metadata for a specific function.
|
|
55
|
-
|
|
52
|
+
|
|
56
53
|
Args:
|
|
57
54
|
name: The function name (case-insensitive)
|
|
58
|
-
|
|
55
|
+
|
|
59
56
|
Returns:
|
|
60
57
|
The function metadata, or None if not found
|
|
61
58
|
"""
|
|
@@ -68,17 +65,17 @@ class FunctionFactory:
|
|
|
68
65
|
sync_only: bool = False
|
|
69
66
|
) -> List[FunctionMetadata]:
|
|
70
67
|
"""Lists all registered functions with their metadata.
|
|
71
|
-
|
|
68
|
+
|
|
72
69
|
Args:
|
|
73
70
|
category: Optional category filter
|
|
74
71
|
async_only: If True, only return async functions
|
|
75
72
|
sync_only: If True, only return sync functions
|
|
76
|
-
|
|
73
|
+
|
|
77
74
|
Returns:
|
|
78
75
|
Array of function metadata
|
|
79
76
|
"""
|
|
80
77
|
result: List[FunctionMetadata] = []
|
|
81
|
-
|
|
78
|
+
|
|
82
79
|
for meta in get_registered_function_metadata():
|
|
83
80
|
if category and meta.category != category:
|
|
84
81
|
continue
|
|
@@ -87,13 +84,13 @@ class FunctionFactory:
|
|
|
87
84
|
if sync_only and meta.category == "async":
|
|
88
85
|
continue
|
|
89
86
|
result.append(meta)
|
|
90
|
-
|
|
87
|
+
|
|
91
88
|
return result
|
|
92
89
|
|
|
93
90
|
@staticmethod
|
|
94
91
|
def list_function_names() -> List[str]:
|
|
95
92
|
"""Lists all registered function names.
|
|
96
|
-
|
|
93
|
+
|
|
97
94
|
Returns:
|
|
98
95
|
Array of function names
|
|
99
96
|
"""
|
|
@@ -102,7 +99,7 @@ class FunctionFactory:
|
|
|
102
99
|
@staticmethod
|
|
103
100
|
def to_json() -> Dict[str, Any]:
|
|
104
101
|
"""Gets all function metadata as a JSON-serializable object for LLM consumption.
|
|
105
|
-
|
|
102
|
+
|
|
106
103
|
Returns:
|
|
107
104
|
Object with functions grouped by category
|
|
108
105
|
"""
|
|
@@ -111,58 +108,58 @@ class FunctionFactory:
|
|
|
111
108
|
return {"functions": functions, "categories": categories}
|
|
112
109
|
|
|
113
110
|
@staticmethod
|
|
114
|
-
def create(name: str) ->
|
|
111
|
+
def create(name: str) -> Any:
|
|
115
112
|
"""Creates a function instance by name.
|
|
116
|
-
|
|
113
|
+
|
|
117
114
|
Args:
|
|
118
115
|
name: The function name (case-insensitive)
|
|
119
|
-
|
|
116
|
+
|
|
120
117
|
Returns:
|
|
121
118
|
A Function instance of the appropriate type
|
|
122
|
-
|
|
119
|
+
|
|
123
120
|
Raises:
|
|
124
121
|
ValueError: If the function name is not registered
|
|
125
122
|
"""
|
|
126
123
|
lower_name = name.lower()
|
|
127
|
-
|
|
124
|
+
|
|
128
125
|
# Check decorator-registered functions
|
|
129
126
|
decorator_factory = get_registered_function_factory(lower_name)
|
|
130
127
|
if decorator_factory:
|
|
131
128
|
return decorator_factory()
|
|
132
|
-
|
|
129
|
+
|
|
133
130
|
raise ValueError(f"Unknown function: {name}")
|
|
134
131
|
|
|
135
132
|
@staticmethod
|
|
136
|
-
def create_predicate(name: str) ->
|
|
133
|
+
def create_predicate(name: str) -> Any:
|
|
137
134
|
"""Creates a predicate function instance by name.
|
|
138
|
-
|
|
135
|
+
|
|
139
136
|
Args:
|
|
140
137
|
name: The function name (case-insensitive)
|
|
141
|
-
|
|
138
|
+
|
|
142
139
|
Returns:
|
|
143
140
|
A PredicateFunction instance of the appropriate type
|
|
144
|
-
|
|
141
|
+
|
|
145
142
|
Raises:
|
|
146
143
|
ValueError: If the predicate function name is not registered
|
|
147
144
|
"""
|
|
148
145
|
lower_name = name.lower()
|
|
149
|
-
|
|
146
|
+
|
|
150
147
|
decorator_factory = get_registered_function_factory(lower_name, "predicate")
|
|
151
148
|
if decorator_factory:
|
|
152
149
|
return decorator_factory()
|
|
153
|
-
|
|
150
|
+
|
|
154
151
|
raise ValueError(f"Unknown predicate function: {name}")
|
|
155
152
|
|
|
156
153
|
@staticmethod
|
|
157
|
-
def create_async(name: str) ->
|
|
154
|
+
def create_async(name: str) -> Any:
|
|
158
155
|
"""Creates an async function instance by name.
|
|
159
|
-
|
|
156
|
+
|
|
160
157
|
Args:
|
|
161
158
|
name: The function name (case-insensitive)
|
|
162
|
-
|
|
159
|
+
|
|
163
160
|
Returns:
|
|
164
161
|
An AsyncFunction instance of the appropriate type
|
|
165
|
-
|
|
162
|
+
|
|
166
163
|
Raises:
|
|
167
164
|
ValueError: If the async function name is not registered
|
|
168
165
|
"""
|