flowquery 1.0.26 → 1.0.28
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/dist/flowquery.min.js +1 -1
- package/dist/graph/relationship.d.ts.map +1 -1
- package/dist/graph/relationship.js +5 -1
- package/dist/graph/relationship.js.map +1 -1
- package/dist/parsing/base_parser.d.ts +1 -1
- package/dist/parsing/base_parser.d.ts.map +1 -1
- package/dist/parsing/base_parser.js.map +1 -1
- package/dist/parsing/expressions/operator.d.ts +37 -1
- package/dist/parsing/expressions/operator.d.ts.map +1 -1
- package/dist/parsing/expressions/operator.js +121 -2
- package/dist/parsing/expressions/operator.js.map +1 -1
- package/dist/parsing/expressions/reference.d.ts +1 -0
- package/dist/parsing/expressions/reference.d.ts.map +1 -1
- package/dist/parsing/expressions/reference.js +3 -0
- package/dist/parsing/expressions/reference.js.map +1 -1
- package/dist/parsing/functions/function_factory.d.ts +1 -0
- package/dist/parsing/functions/function_factory.d.ts.map +1 -1
- package/dist/parsing/functions/function_factory.js +1 -0
- package/dist/parsing/functions/function_factory.js.map +1 -1
- package/dist/parsing/functions/string_distance.d.ts +7 -0
- package/dist/parsing/functions/string_distance.d.ts.map +1 -0
- package/dist/parsing/functions/string_distance.js +84 -0
- package/dist/parsing/functions/string_distance.js.map +1 -0
- package/dist/parsing/parser.d.ts +6 -0
- package/dist/parsing/parser.d.ts.map +1 -1
- package/dist/parsing/parser.js +127 -15
- package/dist/parsing/parser.js.map +1 -1
- package/dist/tokenization/keyword.d.ts +4 -1
- package/dist/tokenization/keyword.d.ts.map +1 -1
- package/dist/tokenization/keyword.js +3 -0
- package/dist/tokenization/keyword.js.map +1 -1
- package/dist/tokenization/token.d.ts +6 -0
- package/dist/tokenization/token.d.ts.map +1 -1
- package/dist/tokenization/token.js +18 -0
- package/dist/tokenization/token.js.map +1 -1
- package/docs/flowquery.min.js +1 -1
- package/flowquery-py/pyproject.toml +1 -1
- package/flowquery-py/src/graph/relationship.py +5 -1
- package/flowquery-py/src/parsing/expressions/__init__.py +4 -0
- package/flowquery-py/src/parsing/expressions/operator.py +102 -0
- package/flowquery-py/src/parsing/functions/__init__.py +2 -0
- package/flowquery-py/src/parsing/functions/string_distance.py +88 -0
- package/flowquery-py/src/parsing/parser.py +120 -10
- package/flowquery-py/src/tokenization/keyword.py +3 -0
- package/flowquery-py/src/tokenization/token.py +21 -0
- package/flowquery-py/tests/compute/test_runner.py +406 -1
- package/flowquery-py/tests/parsing/test_expression.py +121 -1
- package/flowquery-py/tests/parsing/test_parser.py +203 -0
- package/flowquery-vscode/flowQueryEngine/flowquery.min.js +1 -1
- package/package.json +1 -1
- package/src/graph/relationship.ts +4 -1
- package/src/parsing/base_parser.ts +1 -1
- package/src/parsing/expressions/operator.ts +129 -1
- package/src/parsing/expressions/reference.ts +8 -5
- package/src/parsing/functions/function_factory.ts +1 -0
- package/src/parsing/functions/string_distance.ts +80 -0
- package/src/parsing/parser.ts +138 -14
- package/src/tokenization/keyword.ts +3 -0
- package/src/tokenization/token.ts +24 -0
- package/tests/compute/runner.test.ts +379 -0
- package/tests/parsing/expression.test.ts +150 -16
- package/tests/parsing/parser.test.ts +200 -0
|
@@ -8,7 +8,9 @@ from flowquery.parsing.functions.function_metadata import FunctionDef
|
|
|
8
8
|
from flowquery.parsing.operations.match import Match
|
|
9
9
|
from flowquery.parsing.operations.create_relationship import CreateRelationship
|
|
10
10
|
from flowquery.graph.node import Node
|
|
11
|
+
from flowquery.graph.node_reference import NodeReference
|
|
11
12
|
from flowquery.graph.relationship import Relationship
|
|
13
|
+
from flowquery.graph.relationship_reference import RelationshipReference
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
# Test async function for CALL operation parsing test
|
|
@@ -821,6 +823,35 @@ class TestParser:
|
|
|
821
823
|
assert relationship.properties.get("since") is not None
|
|
822
824
|
assert relationship.properties["since"].value() == 2022
|
|
823
825
|
|
|
826
|
+
def test_node_reference_with_label_creates_node_reference(self):
|
|
827
|
+
"""Test that reusing a variable with a label creates a NodeReference instead of a new node."""
|
|
828
|
+
parser = Parser()
|
|
829
|
+
ast = parser.parse("MATCH (n:Person)-[:KNOWS]->(n:Person) RETURN n")
|
|
830
|
+
match_op = ast.first_child()
|
|
831
|
+
assert isinstance(match_op, Match)
|
|
832
|
+
first_node = match_op.patterns[0].chain[0]
|
|
833
|
+
second_node = match_op.patterns[0].chain[2]
|
|
834
|
+
assert isinstance(first_node, Node)
|
|
835
|
+
assert first_node.identifier == "n"
|
|
836
|
+
assert first_node.label == "Person"
|
|
837
|
+
assert isinstance(second_node, NodeReference)
|
|
838
|
+
assert second_node.reference.identifier == "n"
|
|
839
|
+
assert second_node.label == "Person"
|
|
840
|
+
|
|
841
|
+
def test_relationship_reference_with_type_creates_relationship_reference(self):
|
|
842
|
+
"""Test that reusing a relationship variable with a type creates a RelationshipReference."""
|
|
843
|
+
parser = Parser()
|
|
844
|
+
ast = parser.parse("MATCH (a:Person)-[r:KNOWS]->(b:Person)-[r:KNOWS]->(c:Person) RETURN a, b, c")
|
|
845
|
+
match_op = ast.first_child()
|
|
846
|
+
assert isinstance(match_op, Match)
|
|
847
|
+
first_rel = match_op.patterns[0].chain[1]
|
|
848
|
+
second_rel = match_op.patterns[0].chain[3]
|
|
849
|
+
assert isinstance(first_rel, Relationship)
|
|
850
|
+
assert first_rel.identifier == "r"
|
|
851
|
+
assert first_rel.type == "KNOWS"
|
|
852
|
+
assert isinstance(second_rel, RelationshipReference)
|
|
853
|
+
assert second_rel.type == "KNOWS"
|
|
854
|
+
|
|
824
855
|
def test_case_statement_with_keywords_as_identifiers(self):
|
|
825
856
|
"""Test that CASE/WHEN/THEN/ELSE/END are not treated as identifiers."""
|
|
826
857
|
parser = Parser()
|
|
@@ -829,3 +860,175 @@ class TestParser:
|
|
|
829
860
|
assert "When" in ast.print()
|
|
830
861
|
assert "Then" in ast.print()
|
|
831
862
|
assert "Else" in ast.print()
|
|
863
|
+
|
|
864
|
+
def test_where_with_in_list_check(self):
|
|
865
|
+
"""Test WHERE with IN list check."""
|
|
866
|
+
parser = Parser()
|
|
867
|
+
ast = parser.parse("with 1 as n where n IN [1, 2, 3] return n")
|
|
868
|
+
expected = (
|
|
869
|
+
"ASTNode\n"
|
|
870
|
+
"- With\n"
|
|
871
|
+
"-- Expression (n)\n"
|
|
872
|
+
"--- Number (1)\n"
|
|
873
|
+
"- Where\n"
|
|
874
|
+
"-- Expression\n"
|
|
875
|
+
"--- In\n"
|
|
876
|
+
"---- Reference (n)\n"
|
|
877
|
+
"---- JSONArray\n"
|
|
878
|
+
"----- Expression\n"
|
|
879
|
+
"------ Number (1)\n"
|
|
880
|
+
"----- Expression\n"
|
|
881
|
+
"------ Number (2)\n"
|
|
882
|
+
"----- Expression\n"
|
|
883
|
+
"------ Number (3)\n"
|
|
884
|
+
"- Return\n"
|
|
885
|
+
"-- Expression (n)\n"
|
|
886
|
+
"--- Reference (n)"
|
|
887
|
+
)
|
|
888
|
+
assert ast.print() == expected
|
|
889
|
+
|
|
890
|
+
def test_where_with_not_in_list_check(self):
|
|
891
|
+
"""Test WHERE with NOT IN list check."""
|
|
892
|
+
parser = Parser()
|
|
893
|
+
ast = parser.parse("with 4 as n where n NOT IN [1, 2, 3] return n")
|
|
894
|
+
expected = (
|
|
895
|
+
"ASTNode\n"
|
|
896
|
+
"- With\n"
|
|
897
|
+
"-- Expression (n)\n"
|
|
898
|
+
"--- Number (4)\n"
|
|
899
|
+
"- Where\n"
|
|
900
|
+
"-- Expression\n"
|
|
901
|
+
"--- NotIn\n"
|
|
902
|
+
"---- Reference (n)\n"
|
|
903
|
+
"---- JSONArray\n"
|
|
904
|
+
"----- Expression\n"
|
|
905
|
+
"------ Number (1)\n"
|
|
906
|
+
"----- Expression\n"
|
|
907
|
+
"------ Number (2)\n"
|
|
908
|
+
"----- Expression\n"
|
|
909
|
+
"------ Number (3)\n"
|
|
910
|
+
"- Return\n"
|
|
911
|
+
"-- Expression (n)\n"
|
|
912
|
+
"--- Reference (n)"
|
|
913
|
+
)
|
|
914
|
+
assert ast.print() == expected
|
|
915
|
+
|
|
916
|
+
def test_where_with_contains(self):
|
|
917
|
+
"""Test WHERE with CONTAINS."""
|
|
918
|
+
parser = Parser()
|
|
919
|
+
ast = parser.parse("with 'hello' as s where s CONTAINS 'ell' return s")
|
|
920
|
+
expected = (
|
|
921
|
+
"ASTNode\n"
|
|
922
|
+
"- With\n"
|
|
923
|
+
"-- Expression (s)\n"
|
|
924
|
+
"--- String (hello)\n"
|
|
925
|
+
"- Where\n"
|
|
926
|
+
"-- Expression\n"
|
|
927
|
+
"--- Contains\n"
|
|
928
|
+
"---- Reference (s)\n"
|
|
929
|
+
"---- String (ell)\n"
|
|
930
|
+
"- Return\n"
|
|
931
|
+
"-- Expression (s)\n"
|
|
932
|
+
"--- Reference (s)"
|
|
933
|
+
)
|
|
934
|
+
assert ast.print() == expected
|
|
935
|
+
|
|
936
|
+
def test_where_with_not_contains(self):
|
|
937
|
+
"""Test WHERE with NOT CONTAINS."""
|
|
938
|
+
parser = Parser()
|
|
939
|
+
ast = parser.parse("with 'hello' as s where s NOT CONTAINS 'xyz' return s")
|
|
940
|
+
expected = (
|
|
941
|
+
"ASTNode\n"
|
|
942
|
+
"- With\n"
|
|
943
|
+
"-- Expression (s)\n"
|
|
944
|
+
"--- String (hello)\n"
|
|
945
|
+
"- Where\n"
|
|
946
|
+
"-- Expression\n"
|
|
947
|
+
"--- NotContains\n"
|
|
948
|
+
"---- Reference (s)\n"
|
|
949
|
+
"---- String (xyz)\n"
|
|
950
|
+
"- Return\n"
|
|
951
|
+
"-- Expression (s)\n"
|
|
952
|
+
"--- Reference (s)"
|
|
953
|
+
)
|
|
954
|
+
assert ast.print() == expected
|
|
955
|
+
|
|
956
|
+
def test_where_with_starts_with(self):
|
|
957
|
+
"""Test WHERE with STARTS WITH."""
|
|
958
|
+
parser = Parser()
|
|
959
|
+
ast = parser.parse("with 'hello' as s where s STARTS WITH 'hel' return s")
|
|
960
|
+
expected = (
|
|
961
|
+
"ASTNode\n"
|
|
962
|
+
"- With\n"
|
|
963
|
+
"-- Expression (s)\n"
|
|
964
|
+
"--- String (hello)\n"
|
|
965
|
+
"- Where\n"
|
|
966
|
+
"-- Expression\n"
|
|
967
|
+
"--- StartsWith\n"
|
|
968
|
+
"---- Reference (s)\n"
|
|
969
|
+
"---- String (hel)\n"
|
|
970
|
+
"- Return\n"
|
|
971
|
+
"-- Expression (s)\n"
|
|
972
|
+
"--- Reference (s)"
|
|
973
|
+
)
|
|
974
|
+
assert ast.print() == expected
|
|
975
|
+
|
|
976
|
+
def test_where_with_not_starts_with(self):
|
|
977
|
+
"""Test WHERE with NOT STARTS WITH."""
|
|
978
|
+
parser = Parser()
|
|
979
|
+
ast = parser.parse("with 'hello' as s where s NOT STARTS WITH 'xyz' return s")
|
|
980
|
+
expected = (
|
|
981
|
+
"ASTNode\n"
|
|
982
|
+
"- With\n"
|
|
983
|
+
"-- Expression (s)\n"
|
|
984
|
+
"--- String (hello)\n"
|
|
985
|
+
"- Where\n"
|
|
986
|
+
"-- Expression\n"
|
|
987
|
+
"--- NotStartsWith\n"
|
|
988
|
+
"---- Reference (s)\n"
|
|
989
|
+
"---- String (xyz)\n"
|
|
990
|
+
"- Return\n"
|
|
991
|
+
"-- Expression (s)\n"
|
|
992
|
+
"--- Reference (s)"
|
|
993
|
+
)
|
|
994
|
+
assert ast.print() == expected
|
|
995
|
+
|
|
996
|
+
def test_where_with_ends_with(self):
|
|
997
|
+
"""Test WHERE with ENDS WITH."""
|
|
998
|
+
parser = Parser()
|
|
999
|
+
ast = parser.parse("with 'hello' as s where s ENDS WITH 'llo' return s")
|
|
1000
|
+
expected = (
|
|
1001
|
+
"ASTNode\n"
|
|
1002
|
+
"- With\n"
|
|
1003
|
+
"-- Expression (s)\n"
|
|
1004
|
+
"--- String (hello)\n"
|
|
1005
|
+
"- Where\n"
|
|
1006
|
+
"-- Expression\n"
|
|
1007
|
+
"--- EndsWith\n"
|
|
1008
|
+
"---- Reference (s)\n"
|
|
1009
|
+
"---- String (llo)\n"
|
|
1010
|
+
"- Return\n"
|
|
1011
|
+
"-- Expression (s)\n"
|
|
1012
|
+
"--- Reference (s)"
|
|
1013
|
+
)
|
|
1014
|
+
assert ast.print() == expected
|
|
1015
|
+
|
|
1016
|
+
def test_where_with_not_ends_with(self):
|
|
1017
|
+
"""Test WHERE with NOT ENDS WITH."""
|
|
1018
|
+
parser = Parser()
|
|
1019
|
+
ast = parser.parse("with 'hello' as s where s NOT ENDS WITH 'xyz' return s")
|
|
1020
|
+
expected = (
|
|
1021
|
+
"ASTNode\n"
|
|
1022
|
+
"- With\n"
|
|
1023
|
+
"-- Expression (s)\n"
|
|
1024
|
+
"--- String (hello)\n"
|
|
1025
|
+
"- Where\n"
|
|
1026
|
+
"-- Expression\n"
|
|
1027
|
+
"--- NotEndsWith\n"
|
|
1028
|
+
"---- Reference (s)\n"
|
|
1029
|
+
"---- String (xyz)\n"
|
|
1030
|
+
"- Return\n"
|
|
1031
|
+
"-- Expression (s)\n"
|
|
1032
|
+
"--- Reference (s)"
|
|
1033
|
+
)
|
|
1034
|
+
assert ast.print() == expected
|