flowquery 1.0.46 → 1.0.47
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/index.d.ts +0 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/package.json +4 -1
- package/.editorconfig +0 -21
- package/.gitattributes +0 -3
- package/.github/workflows/npm-publish.yml +0 -32
- package/.github/workflows/python-publish.yml +0 -143
- package/.github/workflows/release.yml +0 -107
- package/.husky/pre-commit +0 -28
- package/.prettierrc +0 -22
- package/CODE_OF_CONDUCT.md +0 -10
- package/FlowQueryLogoIcon.png +0 -0
- package/SECURITY.md +0 -14
- package/SUPPORT.md +0 -13
- package/docs/flowquery.min.js +0 -1
- package/docs/index.html +0 -105
- package/flowquery-py/CONTRIBUTING.md +0 -127
- package/flowquery-py/README.md +0 -67
- package/flowquery-py/misc/data/test.json +0 -10
- package/flowquery-py/misc/data/users.json +0 -242
- package/flowquery-py/notebooks/TestFlowQuery.ipynb +0 -440
- package/flowquery-py/pyproject.toml +0 -121
- package/flowquery-py/setup_env.ps1 +0 -92
- package/flowquery-py/setup_env.sh +0 -87
- package/flowquery-py/src/__init__.py +0 -38
- package/flowquery-py/src/__main__.py +0 -10
- package/flowquery-py/src/compute/__init__.py +0 -6
- package/flowquery-py/src/compute/flowquery.py +0 -68
- package/flowquery-py/src/compute/runner.py +0 -64
- package/flowquery-py/src/extensibility.py +0 -52
- package/flowquery-py/src/graph/__init__.py +0 -31
- package/flowquery-py/src/graph/data.py +0 -136
- package/flowquery-py/src/graph/database.py +0 -141
- package/flowquery-py/src/graph/hops.py +0 -43
- package/flowquery-py/src/graph/node.py +0 -143
- package/flowquery-py/src/graph/node_data.py +0 -26
- package/flowquery-py/src/graph/node_reference.py +0 -50
- package/flowquery-py/src/graph/pattern.py +0 -115
- package/flowquery-py/src/graph/pattern_expression.py +0 -67
- package/flowquery-py/src/graph/patterns.py +0 -42
- package/flowquery-py/src/graph/physical_node.py +0 -41
- package/flowquery-py/src/graph/physical_relationship.py +0 -36
- package/flowquery-py/src/graph/relationship.py +0 -193
- package/flowquery-py/src/graph/relationship_data.py +0 -36
- package/flowquery-py/src/graph/relationship_match_collector.py +0 -85
- package/flowquery-py/src/graph/relationship_reference.py +0 -21
- package/flowquery-py/src/io/__init__.py +0 -5
- package/flowquery-py/src/io/command_line.py +0 -108
- package/flowquery-py/src/parsing/__init__.py +0 -17
- package/flowquery-py/src/parsing/alias.py +0 -20
- package/flowquery-py/src/parsing/alias_option.py +0 -11
- package/flowquery-py/src/parsing/ast_node.py +0 -147
- package/flowquery-py/src/parsing/base_parser.py +0 -84
- package/flowquery-py/src/parsing/components/__init__.py +0 -19
- package/flowquery-py/src/parsing/components/csv.py +0 -8
- package/flowquery-py/src/parsing/components/from_.py +0 -12
- package/flowquery-py/src/parsing/components/headers.py +0 -12
- package/flowquery-py/src/parsing/components/json.py +0 -8
- package/flowquery-py/src/parsing/components/null.py +0 -10
- package/flowquery-py/src/parsing/components/post.py +0 -8
- package/flowquery-py/src/parsing/components/text.py +0 -8
- package/flowquery-py/src/parsing/context.py +0 -50
- package/flowquery-py/src/parsing/data_structures/__init__.py +0 -15
- package/flowquery-py/src/parsing/data_structures/associative_array.py +0 -41
- package/flowquery-py/src/parsing/data_structures/json_array.py +0 -30
- package/flowquery-py/src/parsing/data_structures/key_value_pair.py +0 -38
- package/flowquery-py/src/parsing/data_structures/lookup.py +0 -51
- package/flowquery-py/src/parsing/data_structures/range_lookup.py +0 -42
- package/flowquery-py/src/parsing/expressions/__init__.py +0 -61
- package/flowquery-py/src/parsing/expressions/boolean.py +0 -20
- package/flowquery-py/src/parsing/expressions/expression.py +0 -141
- package/flowquery-py/src/parsing/expressions/expression_map.py +0 -26
- package/flowquery-py/src/parsing/expressions/f_string.py +0 -27
- package/flowquery-py/src/parsing/expressions/identifier.py +0 -21
- package/flowquery-py/src/parsing/expressions/number.py +0 -32
- package/flowquery-py/src/parsing/expressions/operator.py +0 -271
- package/flowquery-py/src/parsing/expressions/reference.py +0 -47
- package/flowquery-py/src/parsing/expressions/string.py +0 -27
- package/flowquery-py/src/parsing/functions/__init__.py +0 -127
- package/flowquery-py/src/parsing/functions/aggregate_function.py +0 -60
- package/flowquery-py/src/parsing/functions/async_function.py +0 -65
- package/flowquery-py/src/parsing/functions/avg.py +0 -55
- package/flowquery-py/src/parsing/functions/coalesce.py +0 -43
- package/flowquery-py/src/parsing/functions/collect.py +0 -75
- package/flowquery-py/src/parsing/functions/count.py +0 -79
- package/flowquery-py/src/parsing/functions/date_.py +0 -61
- package/flowquery-py/src/parsing/functions/datetime_.py +0 -62
- package/flowquery-py/src/parsing/functions/duration.py +0 -159
- package/flowquery-py/src/parsing/functions/element_id.py +0 -50
- package/flowquery-py/src/parsing/functions/function.py +0 -68
- package/flowquery-py/src/parsing/functions/function_factory.py +0 -170
- package/flowquery-py/src/parsing/functions/function_metadata.py +0 -148
- package/flowquery-py/src/parsing/functions/functions.py +0 -67
- package/flowquery-py/src/parsing/functions/head.py +0 -39
- package/flowquery-py/src/parsing/functions/id_.py +0 -49
- package/flowquery-py/src/parsing/functions/join.py +0 -49
- package/flowquery-py/src/parsing/functions/keys.py +0 -34
- package/flowquery-py/src/parsing/functions/last.py +0 -39
- package/flowquery-py/src/parsing/functions/localdatetime.py +0 -60
- package/flowquery-py/src/parsing/functions/localtime.py +0 -57
- package/flowquery-py/src/parsing/functions/max_.py +0 -49
- package/flowquery-py/src/parsing/functions/min_.py +0 -49
- package/flowquery-py/src/parsing/functions/nodes.py +0 -48
- package/flowquery-py/src/parsing/functions/predicate_function.py +0 -47
- package/flowquery-py/src/parsing/functions/predicate_sum.py +0 -49
- package/flowquery-py/src/parsing/functions/properties.py +0 -50
- package/flowquery-py/src/parsing/functions/rand.py +0 -28
- package/flowquery-py/src/parsing/functions/range_.py +0 -41
- package/flowquery-py/src/parsing/functions/reducer_element.py +0 -15
- package/flowquery-py/src/parsing/functions/relationships.py +0 -46
- package/flowquery-py/src/parsing/functions/replace.py +0 -39
- package/flowquery-py/src/parsing/functions/round_.py +0 -34
- package/flowquery-py/src/parsing/functions/schema.py +0 -40
- package/flowquery-py/src/parsing/functions/size.py +0 -34
- package/flowquery-py/src/parsing/functions/split.py +0 -54
- package/flowquery-py/src/parsing/functions/string_distance.py +0 -92
- package/flowquery-py/src/parsing/functions/stringify.py +0 -49
- package/flowquery-py/src/parsing/functions/substring.py +0 -76
- package/flowquery-py/src/parsing/functions/sum.py +0 -51
- package/flowquery-py/src/parsing/functions/tail.py +0 -37
- package/flowquery-py/src/parsing/functions/temporal_utils.py +0 -186
- package/flowquery-py/src/parsing/functions/time_.py +0 -57
- package/flowquery-py/src/parsing/functions/timestamp.py +0 -37
- package/flowquery-py/src/parsing/functions/to_float.py +0 -46
- package/flowquery-py/src/parsing/functions/to_integer.py +0 -46
- package/flowquery-py/src/parsing/functions/to_json.py +0 -35
- package/flowquery-py/src/parsing/functions/to_lower.py +0 -37
- package/flowquery-py/src/parsing/functions/to_string.py +0 -41
- package/flowquery-py/src/parsing/functions/trim.py +0 -37
- package/flowquery-py/src/parsing/functions/type_.py +0 -47
- package/flowquery-py/src/parsing/functions/value_holder.py +0 -24
- package/flowquery-py/src/parsing/logic/__init__.py +0 -15
- package/flowquery-py/src/parsing/logic/case.py +0 -28
- package/flowquery-py/src/parsing/logic/else_.py +0 -12
- package/flowquery-py/src/parsing/logic/end.py +0 -8
- package/flowquery-py/src/parsing/logic/then.py +0 -12
- package/flowquery-py/src/parsing/logic/when.py +0 -12
- package/flowquery-py/src/parsing/operations/__init__.py +0 -46
- package/flowquery-py/src/parsing/operations/aggregated_return.py +0 -25
- package/flowquery-py/src/parsing/operations/aggregated_with.py +0 -22
- package/flowquery-py/src/parsing/operations/call.py +0 -73
- package/flowquery-py/src/parsing/operations/create_node.py +0 -35
- package/flowquery-py/src/parsing/operations/create_relationship.py +0 -35
- package/flowquery-py/src/parsing/operations/delete_node.py +0 -29
- package/flowquery-py/src/parsing/operations/delete_relationship.py +0 -29
- package/flowquery-py/src/parsing/operations/group_by.py +0 -148
- package/flowquery-py/src/parsing/operations/limit.py +0 -33
- package/flowquery-py/src/parsing/operations/load.py +0 -148
- package/flowquery-py/src/parsing/operations/match.py +0 -52
- package/flowquery-py/src/parsing/operations/operation.py +0 -69
- package/flowquery-py/src/parsing/operations/order_by.py +0 -114
- package/flowquery-py/src/parsing/operations/projection.py +0 -21
- package/flowquery-py/src/parsing/operations/return_op.py +0 -88
- package/flowquery-py/src/parsing/operations/union.py +0 -115
- package/flowquery-py/src/parsing/operations/union_all.py +0 -17
- package/flowquery-py/src/parsing/operations/unwind.py +0 -42
- package/flowquery-py/src/parsing/operations/where.py +0 -43
- package/flowquery-py/src/parsing/operations/with_op.py +0 -18
- package/flowquery-py/src/parsing/parser.py +0 -1384
- package/flowquery-py/src/parsing/parser_state.py +0 -26
- package/flowquery-py/src/parsing/token_to_node.py +0 -109
- package/flowquery-py/src/tokenization/__init__.py +0 -23
- package/flowquery-py/src/tokenization/keyword.py +0 -54
- package/flowquery-py/src/tokenization/operator.py +0 -29
- package/flowquery-py/src/tokenization/string_walker.py +0 -158
- package/flowquery-py/src/tokenization/symbol.py +0 -19
- package/flowquery-py/src/tokenization/token.py +0 -693
- package/flowquery-py/src/tokenization/token_mapper.py +0 -53
- package/flowquery-py/src/tokenization/token_type.py +0 -21
- package/flowquery-py/src/tokenization/tokenizer.py +0 -214
- package/flowquery-py/src/tokenization/trie.py +0 -125
- package/flowquery-py/src/utils/__init__.py +0 -6
- package/flowquery-py/src/utils/object_utils.py +0 -20
- package/flowquery-py/src/utils/string_utils.py +0 -113
- package/flowquery-py/tests/__init__.py +0 -1
- package/flowquery-py/tests/compute/__init__.py +0 -1
- package/flowquery-py/tests/compute/test_runner.py +0 -4902
- package/flowquery-py/tests/graph/__init__.py +0 -1
- package/flowquery-py/tests/graph/test_create.py +0 -56
- package/flowquery-py/tests/graph/test_data.py +0 -73
- package/flowquery-py/tests/graph/test_match.py +0 -40
- package/flowquery-py/tests/parsing/__init__.py +0 -1
- package/flowquery-py/tests/parsing/test_context.py +0 -34
- package/flowquery-py/tests/parsing/test_expression.py +0 -248
- package/flowquery-py/tests/parsing/test_parser.py +0 -1237
- package/flowquery-py/tests/test_extensibility.py +0 -611
- package/flowquery-py/tests/tokenization/__init__.py +0 -1
- package/flowquery-py/tests/tokenization/test_token_mapper.py +0 -60
- package/flowquery-py/tests/tokenization/test_tokenizer.py +0 -198
- package/flowquery-py/tests/tokenization/test_trie.py +0 -30
- package/flowquery-vscode/.vscode-test.mjs +0 -5
- package/flowquery-vscode/.vscodeignore +0 -13
- package/flowquery-vscode/LICENSE +0 -21
- package/flowquery-vscode/README.md +0 -11
- package/flowquery-vscode/demo/FlowQueryVSCodeDemo.gif +0 -0
- package/flowquery-vscode/eslint.config.mjs +0 -25
- package/flowquery-vscode/extension.js +0 -508
- package/flowquery-vscode/flowQueryEngine/flowquery.min.js +0 -1
- package/flowquery-vscode/flowquery-worker.js +0 -66
- package/flowquery-vscode/images/FlowQueryLogoIcon.png +0 -0
- package/flowquery-vscode/jsconfig.json +0 -13
- package/flowquery-vscode/libs/page.css +0 -53
- package/flowquery-vscode/libs/table.css +0 -13
- package/flowquery-vscode/libs/tabs.css +0 -66
- package/flowquery-vscode/package-lock.json +0 -2917
- package/flowquery-vscode/package.json +0 -51
- package/flowquery-vscode/test/extension.test.js +0 -196
- package/flowquery-vscode/test/worker.test.js +0 -25
- package/flowquery-vscode/vsc-extension-quickstart.md +0 -42
- package/jest.config.js +0 -14
- package/misc/apps/RAG/README.md +0 -29
- package/misc/apps/RAG/data/chats.json +0 -302
- package/misc/apps/RAG/data/emails.json +0 -182
- package/misc/apps/RAG/data/events.json +0 -226
- package/misc/apps/RAG/data/files.json +0 -172
- package/misc/apps/RAG/data/users.json +0 -158
- package/misc/apps/RAG/jest.config.js +0 -21
- package/misc/apps/RAG/package.json +0 -48
- package/misc/apps/RAG/public/index.html +0 -18
- package/misc/apps/RAG/src/App.css +0 -42
- package/misc/apps/RAG/src/App.tsx +0 -50
- package/misc/apps/RAG/src/components/AdaptiveCardRenderer.css +0 -172
- package/misc/apps/RAG/src/components/AdaptiveCardRenderer.tsx +0 -380
- package/misc/apps/RAG/src/components/ApiKeySettings.tsx +0 -245
- package/misc/apps/RAG/src/components/ChatContainer.css +0 -67
- package/misc/apps/RAG/src/components/ChatContainer.tsx +0 -242
- package/misc/apps/RAG/src/components/ChatInput.css +0 -23
- package/misc/apps/RAG/src/components/ChatInput.tsx +0 -76
- package/misc/apps/RAG/src/components/ChatMessage.css +0 -160
- package/misc/apps/RAG/src/components/ChatMessage.tsx +0 -286
- package/misc/apps/RAG/src/components/FlowQueryAgent.ts +0 -708
- package/misc/apps/RAG/src/components/FlowQueryRunner.css +0 -113
- package/misc/apps/RAG/src/components/FlowQueryRunner.tsx +0 -371
- package/misc/apps/RAG/src/components/index.ts +0 -28
- package/misc/apps/RAG/src/graph/index.ts +0 -19
- package/misc/apps/RAG/src/graph/initializeGraph.ts +0 -254
- package/misc/apps/RAG/src/index.tsx +0 -29
- package/misc/apps/RAG/src/prompts/FlowQuerySystemPrompt.ts +0 -327
- package/misc/apps/RAG/src/prompts/index.ts +0 -10
- package/misc/apps/RAG/src/tests/graph.test.ts +0 -35
- package/misc/apps/RAG/src/utils/FlowQueryExecutor.ts +0 -130
- package/misc/apps/RAG/src/utils/FlowQueryExtractor.ts +0 -208
- package/misc/apps/RAG/src/utils/Llm.ts +0 -248
- package/misc/apps/RAG/src/utils/index.ts +0 -12
- package/misc/apps/RAG/tsconfig.json +0 -22
- package/misc/apps/RAG/webpack.config.js +0 -43
- package/misc/apps/README.md +0 -1
- package/misc/queries/analyze_catfacts.cql +0 -75
- package/misc/queries/azure_openai_completions.cql +0 -13
- package/misc/queries/azure_openai_models.cql +0 -9
- package/misc/queries/mock_pipeline.cql +0 -84
- package/misc/queries/openai_completions.cql +0 -15
- package/misc/queries/openai_models.cql +0 -13
- package/misc/queries/test.cql +0 -6
- package/misc/queries/tool_inference.cql +0 -24
- package/misc/queries/wisdom.cql +0 -6
- package/misc/queries/wisdom_letter_histogram.cql +0 -8
- package/src/compute/flowquery.ts +0 -46
- package/src/compute/runner.ts +0 -66
- package/src/extensibility.ts +0 -45
- package/src/graph/data.ts +0 -130
- package/src/graph/database.ts +0 -143
- package/src/graph/hops.ts +0 -22
- package/src/graph/node.ts +0 -122
- package/src/graph/node_data.ts +0 -18
- package/src/graph/node_reference.ts +0 -38
- package/src/graph/pattern.ts +0 -110
- package/src/graph/pattern_expression.ts +0 -48
- package/src/graph/patterns.ts +0 -36
- package/src/graph/physical_node.ts +0 -23
- package/src/graph/physical_relationship.ts +0 -23
- package/src/graph/relationship.ts +0 -167
- package/src/graph/relationship_data.ts +0 -31
- package/src/graph/relationship_match_collector.ts +0 -64
- package/src/graph/relationship_reference.ts +0 -25
- package/src/index.browser.ts +0 -46
- package/src/index.node.ts +0 -55
- package/src/index.ts +0 -12
- package/src/io/command_line.ts +0 -74
- package/src/parsing/alias.ts +0 -23
- package/src/parsing/alias_option.ts +0 -5
- package/src/parsing/ast_node.ts +0 -153
- package/src/parsing/base_parser.ts +0 -98
- package/src/parsing/components/csv.ts +0 -9
- package/src/parsing/components/from.ts +0 -12
- package/src/parsing/components/headers.ts +0 -12
- package/src/parsing/components/json.ts +0 -9
- package/src/parsing/components/null.ts +0 -9
- package/src/parsing/components/post.ts +0 -9
- package/src/parsing/components/text.ts +0 -9
- package/src/parsing/context.ts +0 -54
- package/src/parsing/data_structures/associative_array.ts +0 -43
- package/src/parsing/data_structures/json_array.ts +0 -31
- package/src/parsing/data_structures/key_value_pair.ts +0 -37
- package/src/parsing/data_structures/lookup.ts +0 -44
- package/src/parsing/data_structures/range_lookup.ts +0 -36
- package/src/parsing/expressions/boolean.ts +0 -21
- package/src/parsing/expressions/expression.ts +0 -150
- package/src/parsing/expressions/expression_map.ts +0 -22
- package/src/parsing/expressions/f_string.ts +0 -26
- package/src/parsing/expressions/identifier.ts +0 -22
- package/src/parsing/expressions/number.ts +0 -40
- package/src/parsing/expressions/operator.ts +0 -354
- package/src/parsing/expressions/reference.ts +0 -45
- package/src/parsing/expressions/string.ts +0 -34
- package/src/parsing/functions/aggregate_function.ts +0 -58
- package/src/parsing/functions/async_function.ts +0 -64
- package/src/parsing/functions/avg.ts +0 -47
- package/src/parsing/functions/coalesce.ts +0 -49
- package/src/parsing/functions/collect.ts +0 -54
- package/src/parsing/functions/count.ts +0 -54
- package/src/parsing/functions/date.ts +0 -63
- package/src/parsing/functions/datetime.ts +0 -63
- package/src/parsing/functions/duration.ts +0 -143
- package/src/parsing/functions/element_id.ts +0 -51
- package/src/parsing/functions/function.ts +0 -60
- package/src/parsing/functions/function_factory.ts +0 -195
- package/src/parsing/functions/function_metadata.ts +0 -217
- package/src/parsing/functions/functions.ts +0 -70
- package/src/parsing/functions/head.ts +0 -42
- package/src/parsing/functions/id.ts +0 -51
- package/src/parsing/functions/join.ts +0 -40
- package/src/parsing/functions/keys.ts +0 -29
- package/src/parsing/functions/last.ts +0 -42
- package/src/parsing/functions/localdatetime.ts +0 -63
- package/src/parsing/functions/localtime.ts +0 -58
- package/src/parsing/functions/max.ts +0 -37
- package/src/parsing/functions/min.ts +0 -37
- package/src/parsing/functions/nodes.ts +0 -54
- package/src/parsing/functions/predicate_function.ts +0 -48
- package/src/parsing/functions/predicate_sum.ts +0 -47
- package/src/parsing/functions/properties.ts +0 -56
- package/src/parsing/functions/rand.ts +0 -21
- package/src/parsing/functions/range.ts +0 -37
- package/src/parsing/functions/reducer_element.ts +0 -10
- package/src/parsing/functions/relationships.ts +0 -52
- package/src/parsing/functions/replace.ts +0 -38
- package/src/parsing/functions/round.ts +0 -28
- package/src/parsing/functions/schema.ts +0 -39
- package/src/parsing/functions/size.ts +0 -28
- package/src/parsing/functions/split.ts +0 -45
- package/src/parsing/functions/string_distance.ts +0 -83
- package/src/parsing/functions/stringify.ts +0 -37
- package/src/parsing/functions/substring.ts +0 -68
- package/src/parsing/functions/sum.ts +0 -41
- package/src/parsing/functions/tail.ts +0 -39
- package/src/parsing/functions/temporal_utils.ts +0 -180
- package/src/parsing/functions/time.ts +0 -58
- package/src/parsing/functions/timestamp.ts +0 -37
- package/src/parsing/functions/to_float.ts +0 -50
- package/src/parsing/functions/to_integer.ts +0 -50
- package/src/parsing/functions/to_json.ts +0 -28
- package/src/parsing/functions/to_lower.ts +0 -28
- package/src/parsing/functions/to_string.ts +0 -32
- package/src/parsing/functions/trim.ts +0 -28
- package/src/parsing/functions/type.ts +0 -39
- package/src/parsing/functions/value_holder.ts +0 -13
- package/src/parsing/logic/case.ts +0 -26
- package/src/parsing/logic/else.ts +0 -12
- package/src/parsing/logic/end.ts +0 -9
- package/src/parsing/logic/then.ts +0 -12
- package/src/parsing/logic/when.ts +0 -12
- package/src/parsing/operations/aggregated_return.ts +0 -22
- package/src/parsing/operations/aggregated_with.ts +0 -18
- package/src/parsing/operations/call.ts +0 -69
- package/src/parsing/operations/create_node.ts +0 -39
- package/src/parsing/operations/create_relationship.ts +0 -38
- package/src/parsing/operations/delete_node.ts +0 -33
- package/src/parsing/operations/delete_relationship.ts +0 -32
- package/src/parsing/operations/group_by.ts +0 -137
- package/src/parsing/operations/limit.ts +0 -31
- package/src/parsing/operations/load.ts +0 -146
- package/src/parsing/operations/match.ts +0 -54
- package/src/parsing/operations/operation.ts +0 -69
- package/src/parsing/operations/order_by.ts +0 -126
- package/src/parsing/operations/projection.ts +0 -18
- package/src/parsing/operations/return.ts +0 -76
- package/src/parsing/operations/union.ts +0 -114
- package/src/parsing/operations/union_all.ts +0 -16
- package/src/parsing/operations/unwind.ts +0 -36
- package/src/parsing/operations/where.ts +0 -42
- package/src/parsing/operations/with.ts +0 -20
- package/src/parsing/parser.ts +0 -1641
- package/src/parsing/parser_state.ts +0 -25
- package/src/parsing/token_to_node.ts +0 -114
- package/src/tokenization/keyword.ts +0 -50
- package/src/tokenization/operator.ts +0 -25
- package/src/tokenization/string_walker.ts +0 -197
- package/src/tokenization/symbol.ts +0 -15
- package/src/tokenization/token.ts +0 -764
- package/src/tokenization/token_mapper.ts +0 -53
- package/src/tokenization/token_type.ts +0 -16
- package/src/tokenization/tokenizer.ts +0 -250
- package/src/tokenization/trie.ts +0 -117
- package/src/utils/object_utils.ts +0 -17
- package/src/utils/string_utils.ts +0 -114
- package/tests/compute/runner.test.ts +0 -4559
- package/tests/extensibility.test.ts +0 -643
- package/tests/graph/create.test.ts +0 -36
- package/tests/graph/data.test.ts +0 -58
- package/tests/graph/match.test.ts +0 -29
- package/tests/parsing/context.test.ts +0 -27
- package/tests/parsing/expression.test.ts +0 -303
- package/tests/parsing/parser.test.ts +0 -1327
- package/tests/tokenization/token_mapper.test.ts +0 -47
- package/tests/tokenization/tokenizer.test.ts +0 -191
- package/tests/tokenization/trie.test.ts +0 -20
- package/tsconfig.json +0 -19
- package/typedoc.json +0 -16
- package/vscode-settings.json.recommended +0 -16
- package/webpack.config.js +0 -26
|
@@ -1,1327 +0,0 @@
|
|
|
1
|
-
import Node from "../../src/graph/node";
|
|
2
|
-
import NodeReference from "../../src/graph/node_reference";
|
|
3
|
-
import Relationship from "../../src/graph/relationship";
|
|
4
|
-
import RelationshipReference from "../../src/graph/relationship_reference";
|
|
5
|
-
import AsyncFunction from "../../src/parsing/functions/async_function";
|
|
6
|
-
import { FunctionDef } from "../../src/parsing/functions/function_metadata";
|
|
7
|
-
import CreateNode from "../../src/parsing/operations/create_node";
|
|
8
|
-
import CreateRelationship from "../../src/parsing/operations/create_relationship";
|
|
9
|
-
import Match from "../../src/parsing/operations/match";
|
|
10
|
-
import Parser from "../../src/parsing/parser";
|
|
11
|
-
|
|
12
|
-
// Test class for CALL operation parsing test - defined at module level for Prettier compatibility
|
|
13
|
-
@FunctionDef({
|
|
14
|
-
description: "Asynchronous function for testing CALL operation",
|
|
15
|
-
category: "async",
|
|
16
|
-
parameters: [],
|
|
17
|
-
output: { description: "Yields test values", type: "any" },
|
|
18
|
-
})
|
|
19
|
-
class Test extends AsyncFunction {
|
|
20
|
-
constructor() {
|
|
21
|
-
super();
|
|
22
|
-
this._expectedParameterCount = 0;
|
|
23
|
-
}
|
|
24
|
-
public async *generate(): AsyncGenerator<any> {
|
|
25
|
-
yield 1;
|
|
26
|
-
yield 2;
|
|
27
|
-
yield 3;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
test("Test Parser", () => {
|
|
32
|
-
const parser = new Parser();
|
|
33
|
-
const ast = parser.parse("RETURN 1, 2, 3");
|
|
34
|
-
expect(ast.print()).toBe(
|
|
35
|
-
"ASTNode\n" +
|
|
36
|
-
"- Return\n" +
|
|
37
|
-
"-- Expression\n" +
|
|
38
|
-
"--- Number (1)\n" +
|
|
39
|
-
"-- Expression\n" +
|
|
40
|
-
"--- Number (2)\n" +
|
|
41
|
-
"-- Expression\n" +
|
|
42
|
-
"--- Number (3)"
|
|
43
|
-
);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test("Test Parser with function", () => {
|
|
47
|
-
const parser = new Parser();
|
|
48
|
-
const ast = parser.parse("RETURN rand()");
|
|
49
|
-
expect(ast.print()).toBe(
|
|
50
|
-
"ASTNode\n" + "- Return\n" + "-- Expression\n" + "--- Function (rand)"
|
|
51
|
-
);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
test("Test Parser with associative array", () => {
|
|
55
|
-
const parser = new Parser();
|
|
56
|
-
const ast = parser.parse("RETURN {a: 1, b: 2}");
|
|
57
|
-
expect(ast.print()).toBe(
|
|
58
|
-
"ASTNode\n" +
|
|
59
|
-
"- Return\n" +
|
|
60
|
-
"-- Expression\n" +
|
|
61
|
-
"--- AssociativeArray\n" +
|
|
62
|
-
"---- KeyValuePair\n" +
|
|
63
|
-
"----- String (a)\n" +
|
|
64
|
-
"----- Expression\n" +
|
|
65
|
-
"------ Number (1)\n" +
|
|
66
|
-
"---- KeyValuePair\n" +
|
|
67
|
-
"----- String (b)\n" +
|
|
68
|
-
"----- Expression\n" +
|
|
69
|
-
"------ Number (2)"
|
|
70
|
-
);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
test("Test Parser with JSON array", () => {
|
|
74
|
-
const parser = new Parser();
|
|
75
|
-
const ast = parser.parse("RETURN [1, 2]");
|
|
76
|
-
expect(ast.print()).toBe(
|
|
77
|
-
"ASTNode\n" +
|
|
78
|
-
"- Return\n" +
|
|
79
|
-
"-- Expression\n" +
|
|
80
|
-
"--- JSONArray\n" +
|
|
81
|
-
"---- Expression\n" +
|
|
82
|
-
"----- Number (1)\n" +
|
|
83
|
-
"---- Expression\n" +
|
|
84
|
-
"----- Number (2)"
|
|
85
|
-
);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
test("Test Parser with nested associative array", () => {
|
|
89
|
-
const parser = new Parser();
|
|
90
|
-
const ast = parser.parse("RETURN {a:{}}");
|
|
91
|
-
expect(ast.print()).toBe(
|
|
92
|
-
"ASTNode\n" +
|
|
93
|
-
"- Return\n" +
|
|
94
|
-
"-- Expression\n" +
|
|
95
|
-
"--- AssociativeArray\n" +
|
|
96
|
-
"---- KeyValuePair\n" +
|
|
97
|
-
"----- String (a)\n" +
|
|
98
|
-
"----- Expression\n" +
|
|
99
|
-
"------ AssociativeArray"
|
|
100
|
-
);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
test("Test Parser with multiple operations", () => {
|
|
104
|
-
const parser = new Parser();
|
|
105
|
-
const ast = parser.parse("WITH 1 AS n RETURN n");
|
|
106
|
-
expect(ast.print()).toBe(
|
|
107
|
-
"ASTNode\n" +
|
|
108
|
-
"- With\n" +
|
|
109
|
-
"-- Expression (n)\n" +
|
|
110
|
-
"--- Number (1)\n" +
|
|
111
|
-
"- Return\n" +
|
|
112
|
-
"-- Expression (n)\n" +
|
|
113
|
-
"--- Reference (n)"
|
|
114
|
-
);
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
test("Test Parser with multiple operations and comments", () => {
|
|
118
|
-
const parser = new Parser();
|
|
119
|
-
const ast = parser.parse("WITH 1 AS n /* comment */ RETURN n");
|
|
120
|
-
expect(ast.print()).toBe(
|
|
121
|
-
"ASTNode\n" +
|
|
122
|
-
"- With\n" +
|
|
123
|
-
"-- Expression (n)\n" +
|
|
124
|
-
"--- Number (1)\n" +
|
|
125
|
-
"- Return\n" +
|
|
126
|
-
"-- Expression (n)\n" +
|
|
127
|
-
"--- Reference (n)"
|
|
128
|
-
);
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
test("Test Parser with multiple operations including UNWIND", () => {
|
|
132
|
-
const parser = new Parser();
|
|
133
|
-
const ast = parser.parse("UNWIND [1, 2, 3] AS n RETURN n");
|
|
134
|
-
expect(ast.print()).toBe(
|
|
135
|
-
"ASTNode\n" +
|
|
136
|
-
"- Unwind\n" +
|
|
137
|
-
"-- Expression (n)\n" +
|
|
138
|
-
"--- JSONArray\n" +
|
|
139
|
-
"---- Expression\n" +
|
|
140
|
-
"----- Number (1)\n" +
|
|
141
|
-
"---- Expression\n" +
|
|
142
|
-
"----- Number (2)\n" +
|
|
143
|
-
"---- Expression\n" +
|
|
144
|
-
"----- Number (3)\n" +
|
|
145
|
-
"- Return\n" +
|
|
146
|
-
"-- Expression (n)\n" +
|
|
147
|
-
"--- Reference (n)"
|
|
148
|
-
);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
test("Test Unwind with invalid expression", () => {
|
|
152
|
-
const parser = new Parser();
|
|
153
|
-
expect(() => parser.parse("UNWIND 1 AS n RETURN n")).toThrow(
|
|
154
|
-
"Expected array, function, reference, or lookup."
|
|
155
|
-
);
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
test("Test Unwind with invalid alias", () => {
|
|
159
|
-
const parser = new Parser();
|
|
160
|
-
expect(() => parser.parse("UNWIND [1, 2, 3] AS 1 RETURN n")).toThrow("Expected identifier");
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
test("Test Unwind with missing alias", () => {
|
|
164
|
-
const parser = new Parser();
|
|
165
|
-
expect(() => parser.parse("UNWIND [1, 2, 3] RETURN n")).toThrow("Expected alias");
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
test("Test statement with where clause", () => {
|
|
169
|
-
const parser = new Parser();
|
|
170
|
-
const ast = parser.parse("with 1 as n where n > 0 return n");
|
|
171
|
-
expect(ast.print()).toBe(
|
|
172
|
-
"ASTNode\n" +
|
|
173
|
-
"- With\n" +
|
|
174
|
-
"-- Expression (n)\n" +
|
|
175
|
-
"--- Number (1)\n" +
|
|
176
|
-
"- Where\n" +
|
|
177
|
-
"-- Expression\n" +
|
|
178
|
-
"--- GreaterThan\n" +
|
|
179
|
-
"---- Reference (n)\n" +
|
|
180
|
-
"---- Number (0)\n" +
|
|
181
|
-
"- Return\n" +
|
|
182
|
-
"-- Expression (n)\n" +
|
|
183
|
-
"--- Reference (n)"
|
|
184
|
-
);
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
test("Test lookup", () => {
|
|
188
|
-
const parser = new Parser();
|
|
189
|
-
const ast = parser.parse("return {a: 1}.a");
|
|
190
|
-
expect(ast.print()).toBe(
|
|
191
|
-
"ASTNode\n" +
|
|
192
|
-
"- Return\n" +
|
|
193
|
-
"-- Expression\n" +
|
|
194
|
-
"--- Lookup\n" +
|
|
195
|
-
"---- Identifier (a)\n" +
|
|
196
|
-
"---- AssociativeArray\n" +
|
|
197
|
-
"----- KeyValuePair\n" +
|
|
198
|
-
"------ String (a)\n" +
|
|
199
|
-
"------ Expression\n" +
|
|
200
|
-
"------- Number (1)"
|
|
201
|
-
);
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
test("Test lookup as part of expression", () => {
|
|
205
|
-
const parser = new Parser();
|
|
206
|
-
const ast = parser.parse("return {a: 1}.a + 1");
|
|
207
|
-
expect(ast.print()).toBe(
|
|
208
|
-
"ASTNode\n" +
|
|
209
|
-
"- Return\n" +
|
|
210
|
-
"-- Expression\n" +
|
|
211
|
-
"--- Add\n" +
|
|
212
|
-
"---- Lookup\n" +
|
|
213
|
-
"----- Identifier (a)\n" +
|
|
214
|
-
"----- AssociativeArray\n" +
|
|
215
|
-
"------ KeyValuePair\n" +
|
|
216
|
-
"------- String (a)\n" +
|
|
217
|
-
"------- Expression\n" +
|
|
218
|
-
"-------- Number (1)\n" +
|
|
219
|
-
"---- Number (1)"
|
|
220
|
-
);
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
test("Test lookup with nested associative array", () => {
|
|
224
|
-
const parser = new Parser();
|
|
225
|
-
const ast = parser.parse("return {a: {b: 1}}.a.b");
|
|
226
|
-
const _return = ast.firstChild();
|
|
227
|
-
expect(ast.print()).toBe(
|
|
228
|
-
"ASTNode\n" +
|
|
229
|
-
"- Return\n" +
|
|
230
|
-
"-- Expression\n" +
|
|
231
|
-
"--- Lookup\n" +
|
|
232
|
-
"---- Identifier (b)\n" +
|
|
233
|
-
"---- Lookup\n" +
|
|
234
|
-
"----- Identifier (a)\n" +
|
|
235
|
-
"----- AssociativeArray\n" +
|
|
236
|
-
"------ KeyValuePair\n" +
|
|
237
|
-
"------- String (a)\n" +
|
|
238
|
-
"------- Expression\n" +
|
|
239
|
-
"-------- AssociativeArray\n" +
|
|
240
|
-
"--------- KeyValuePair\n" +
|
|
241
|
-
"---------- String (b)\n" +
|
|
242
|
-
"---------- Expression\n" +
|
|
243
|
-
"----------- Number (1)"
|
|
244
|
-
);
|
|
245
|
-
expect(_return.firstChild().value()).toBe(1);
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
test("Test lookup with JSON array", () => {
|
|
249
|
-
const parser = new Parser();
|
|
250
|
-
const ast = parser.parse("return [1, 2][1]");
|
|
251
|
-
const _return = ast.firstChild();
|
|
252
|
-
expect(ast.print()).toBe(
|
|
253
|
-
"ASTNode\n" +
|
|
254
|
-
"- Return\n" +
|
|
255
|
-
"-- Expression\n" +
|
|
256
|
-
"--- Lookup\n" +
|
|
257
|
-
"---- Expression\n" +
|
|
258
|
-
"----- Number (1)\n" +
|
|
259
|
-
"---- JSONArray\n" +
|
|
260
|
-
"----- Expression\n" +
|
|
261
|
-
"------ Number (1)\n" +
|
|
262
|
-
"----- Expression\n" +
|
|
263
|
-
"------ Number (2)"
|
|
264
|
-
);
|
|
265
|
-
expect(_return.firstChild().value()).toBe(2);
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
test("Test lookup with from keyword as property name", () => {
|
|
269
|
-
const parser = new Parser();
|
|
270
|
-
const ast = parser.parse("with {from: 1, to: 2} as x return x.from, x.to");
|
|
271
|
-
expect(ast.print()).toBe(
|
|
272
|
-
"ASTNode\n" +
|
|
273
|
-
"- With\n" +
|
|
274
|
-
"-- Expression (x)\n" +
|
|
275
|
-
"--- AssociativeArray\n" +
|
|
276
|
-
"---- KeyValuePair\n" +
|
|
277
|
-
"----- String (from)\n" +
|
|
278
|
-
"----- Expression\n" +
|
|
279
|
-
"------ Number (1)\n" +
|
|
280
|
-
"---- KeyValuePair\n" +
|
|
281
|
-
"----- String (to)\n" +
|
|
282
|
-
"----- Expression\n" +
|
|
283
|
-
"------ Number (2)\n" +
|
|
284
|
-
"- Return\n" +
|
|
285
|
-
"-- Expression\n" +
|
|
286
|
-
"--- Lookup\n" +
|
|
287
|
-
"---- Identifier (from)\n" +
|
|
288
|
-
"---- Reference (x)\n" +
|
|
289
|
-
"-- Expression\n" +
|
|
290
|
-
"--- Lookup\n" +
|
|
291
|
-
"---- Identifier (to)\n" +
|
|
292
|
-
"---- Reference (x)"
|
|
293
|
-
);
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
test("Test camelCase alias starting with keyword", () => {
|
|
297
|
-
const parser = new Parser();
|
|
298
|
-
const ast = parser.parse("LOAD JSON FROM '/data.json' AS x RETURN x.from AS fromUser");
|
|
299
|
-
expect(ast.print()).toContain("Lookup");
|
|
300
|
-
expect(ast.print()).toContain("Identifier (from)");
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
test("Test from keyword property in create virtual subquery", () => {
|
|
304
|
-
const parser = new Parser();
|
|
305
|
-
// Should not throw - email.from should be parsed correctly even with FROM being a keyword
|
|
306
|
-
expect(() => {
|
|
307
|
-
parser.parse(
|
|
308
|
-
"CREATE VIRTUAL (:Email) AS { LOAD JSON FROM '/data/emails.json' AS email RETURN email.id AS id, email.from AS fromUser }"
|
|
309
|
-
);
|
|
310
|
-
}).not.toThrow();
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
test("Test lookup with reserved keyword property names", () => {
|
|
314
|
-
const parser = new Parser();
|
|
315
|
-
const ast = parser.parse("with {end: 1, null: 2, case: 3} as x return x.end, x.null, x.case");
|
|
316
|
-
expect(ast.print()).toBe(
|
|
317
|
-
"ASTNode\n" +
|
|
318
|
-
"- With\n" +
|
|
319
|
-
"-- Expression (x)\n" +
|
|
320
|
-
"--- AssociativeArray\n" +
|
|
321
|
-
"---- KeyValuePair\n" +
|
|
322
|
-
"----- String (end)\n" +
|
|
323
|
-
"----- Expression\n" +
|
|
324
|
-
"------ Number (1)\n" +
|
|
325
|
-
"---- KeyValuePair\n" +
|
|
326
|
-
"----- String (null)\n" +
|
|
327
|
-
"----- Expression\n" +
|
|
328
|
-
"------ Number (2)\n" +
|
|
329
|
-
"---- KeyValuePair\n" +
|
|
330
|
-
"----- String (case)\n" +
|
|
331
|
-
"----- Expression\n" +
|
|
332
|
-
"------ Number (3)\n" +
|
|
333
|
-
"- Return\n" +
|
|
334
|
-
"-- Expression\n" +
|
|
335
|
-
"--- Lookup\n" +
|
|
336
|
-
"---- Identifier (end)\n" +
|
|
337
|
-
"---- Reference (x)\n" +
|
|
338
|
-
"-- Expression\n" +
|
|
339
|
-
"--- Lookup\n" +
|
|
340
|
-
"---- Identifier (null)\n" +
|
|
341
|
-
"---- Reference (x)\n" +
|
|
342
|
-
"-- Expression\n" +
|
|
343
|
-
"--- Lookup\n" +
|
|
344
|
-
"---- Identifier (case)\n" +
|
|
345
|
-
"---- Reference (x)"
|
|
346
|
-
);
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
test("Test load with post", () => {
|
|
350
|
-
const parser = new Parser();
|
|
351
|
-
const ast = parser.parse(
|
|
352
|
-
'load json from "https://jsonplaceholder.typicode.com/posts" post {userId: 1} as data return data'
|
|
353
|
-
);
|
|
354
|
-
expect(ast.print()).toBe(
|
|
355
|
-
"ASTNode\n" +
|
|
356
|
-
"- Load\n" +
|
|
357
|
-
"-- JSON\n" +
|
|
358
|
-
"-- From\n" +
|
|
359
|
-
"--- Expression\n" +
|
|
360
|
-
"---- String (https://jsonplaceholder.typicode.com/posts)\n" +
|
|
361
|
-
"-- Post\n" +
|
|
362
|
-
"--- Expression\n" +
|
|
363
|
-
"---- AssociativeArray\n" +
|
|
364
|
-
"----- KeyValuePair\n" +
|
|
365
|
-
"------ String (userId)\n" +
|
|
366
|
-
"------ Expression\n" +
|
|
367
|
-
"------- Number (1)\n" +
|
|
368
|
-
"-- Alias (data)\n" +
|
|
369
|
-
"- Return\n" +
|
|
370
|
-
"-- Expression (data)\n" +
|
|
371
|
-
"--- Reference (data)"
|
|
372
|
-
);
|
|
373
|
-
});
|
|
374
|
-
|
|
375
|
-
test("Test nested aggregate functions", () => {
|
|
376
|
-
expect(() => {
|
|
377
|
-
const parser = new Parser();
|
|
378
|
-
parser.parse("RETURN sum(sum(1))");
|
|
379
|
-
}).toThrow("Aggregate functions cannot be nested");
|
|
380
|
-
});
|
|
381
|
-
|
|
382
|
-
test("Test with and return with renamed variable", () => {
|
|
383
|
-
const parser = new Parser();
|
|
384
|
-
const ast = parser.parse("WITH 1 AS n RETURN n AS m");
|
|
385
|
-
expect(ast.print()).toBe(
|
|
386
|
-
"ASTNode\n" +
|
|
387
|
-
"- With\n" +
|
|
388
|
-
"-- Expression (n)\n" +
|
|
389
|
-
"--- Number (1)\n" +
|
|
390
|
-
"- Return\n" +
|
|
391
|
-
"-- Expression (m)\n" +
|
|
392
|
-
"--- Reference (n)"
|
|
393
|
-
);
|
|
394
|
-
});
|
|
395
|
-
|
|
396
|
-
test("Test with and return with variable lookup", () => {
|
|
397
|
-
const parser = new Parser();
|
|
398
|
-
const ast = parser.parse("WITH {a: n} AS obj RETURN obj.a");
|
|
399
|
-
expect(ast.print()).toBe(
|
|
400
|
-
"ASTNode\n" +
|
|
401
|
-
"- With\n" +
|
|
402
|
-
"-- Expression (obj)\n" +
|
|
403
|
-
"--- AssociativeArray\n" +
|
|
404
|
-
"---- KeyValuePair\n" +
|
|
405
|
-
"----- String (a)\n" +
|
|
406
|
-
"----- Expression\n" +
|
|
407
|
-
"------ Reference (n)\n" +
|
|
408
|
-
"- Return\n" +
|
|
409
|
-
"-- Expression\n" +
|
|
410
|
-
"--- Lookup\n" +
|
|
411
|
-
"---- Identifier (a)\n" +
|
|
412
|
-
"---- Reference (obj)"
|
|
413
|
-
);
|
|
414
|
-
});
|
|
415
|
-
|
|
416
|
-
test("Test unwind", () => {
|
|
417
|
-
const parser = new Parser();
|
|
418
|
-
const ast = parser.parse("WITH [1, 2, 4] as n unwind n as i return i");
|
|
419
|
-
expect(ast.print()).toBe(
|
|
420
|
-
"ASTNode\n" +
|
|
421
|
-
"- With\n" +
|
|
422
|
-
"-- Expression (n)\n" +
|
|
423
|
-
"--- JSONArray\n" +
|
|
424
|
-
"---- Expression\n" +
|
|
425
|
-
"----- Number (1)\n" +
|
|
426
|
-
"---- Expression\n" +
|
|
427
|
-
"----- Number (2)\n" +
|
|
428
|
-
"---- Expression\n" +
|
|
429
|
-
"----- Number (4)\n" +
|
|
430
|
-
"- Unwind\n" +
|
|
431
|
-
"-- Expression (i)\n" +
|
|
432
|
-
"--- Reference (n)\n" +
|
|
433
|
-
"- Return\n" +
|
|
434
|
-
"-- Expression (i)\n" +
|
|
435
|
-
"--- Reference (i)"
|
|
436
|
-
);
|
|
437
|
-
});
|
|
438
|
-
|
|
439
|
-
test("Test predicate function", () => {
|
|
440
|
-
const parser = new Parser();
|
|
441
|
-
const ast = parser.parse("RETURN sum(n in [1, 2, 3] | n where n > 1)");
|
|
442
|
-
expect(ast.print()).toBe(
|
|
443
|
-
"ASTNode\n" +
|
|
444
|
-
"- Return\n" +
|
|
445
|
-
"-- Expression\n" +
|
|
446
|
-
"--- PredicateFunction (sum)\n" +
|
|
447
|
-
"---- Reference (n)\n" +
|
|
448
|
-
"---- Expression\n" +
|
|
449
|
-
"----- JSONArray\n" +
|
|
450
|
-
"------ Expression\n" +
|
|
451
|
-
"------- Number (1)\n" +
|
|
452
|
-
"------ Expression\n" +
|
|
453
|
-
"------- Number (2)\n" +
|
|
454
|
-
"------ Expression\n" +
|
|
455
|
-
"------- Number (3)\n" +
|
|
456
|
-
"---- Expression\n" +
|
|
457
|
-
"----- Reference (n)\n" +
|
|
458
|
-
"---- Where\n" +
|
|
459
|
-
"----- Expression\n" +
|
|
460
|
-
"------ GreaterThan\n" +
|
|
461
|
-
"------- Reference (n)\n" +
|
|
462
|
-
"------- Number (1)"
|
|
463
|
-
);
|
|
464
|
-
});
|
|
465
|
-
|
|
466
|
-
test("Test case statement", () => {
|
|
467
|
-
const parser = new Parser();
|
|
468
|
-
const ast = parser.parse("RETURN CASE WHEN 1 THEN 2 ELSE 3 END");
|
|
469
|
-
expect(ast.print()).toBe(
|
|
470
|
-
"ASTNode\n" +
|
|
471
|
-
"- Return\n" +
|
|
472
|
-
"-- Expression\n" +
|
|
473
|
-
"--- Case\n" +
|
|
474
|
-
"---- When\n" +
|
|
475
|
-
"----- Expression\n" +
|
|
476
|
-
"------ Number (1)\n" +
|
|
477
|
-
"---- Then\n" +
|
|
478
|
-
"----- Expression\n" +
|
|
479
|
-
"------ Number (2)\n" +
|
|
480
|
-
"---- Else\n" +
|
|
481
|
-
"----- Expression\n" +
|
|
482
|
-
"------ Number (3)"
|
|
483
|
-
);
|
|
484
|
-
});
|
|
485
|
-
|
|
486
|
-
test("Test case statement with keywords as identifiers", () => {
|
|
487
|
-
const parser = new Parser();
|
|
488
|
-
const ast = parser.parse("RETURN CASE WHEN 1 THEN 2 ELSE 3 END");
|
|
489
|
-
expect(ast.print()).toContain("Case");
|
|
490
|
-
expect(ast.print()).toContain("When");
|
|
491
|
-
expect(ast.print()).toContain("Then");
|
|
492
|
-
expect(ast.print()).toContain("Else");
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
test("Test functions with wrong number of arguments", () => {
|
|
496
|
-
expect(() => new Parser().parse("RETURN range(1)")).toThrow(
|
|
497
|
-
"Function range expected 2 parameters, but got 1"
|
|
498
|
-
);
|
|
499
|
-
expect(() => new Parser().parse("RETURN range(1, 2, 3)")).toThrow(
|
|
500
|
-
"Function range expected 2 parameters, but got 3"
|
|
501
|
-
);
|
|
502
|
-
expect(() => new Parser().parse("RETURN avg(1, 2, 3)")).toThrow(
|
|
503
|
-
"Function avg expected 1 parameters, but got 3"
|
|
504
|
-
);
|
|
505
|
-
expect(() => new Parser().parse("RETURN sum(1, 2)")).toThrow(
|
|
506
|
-
"Function sum expected 1 parameters, but got 2"
|
|
507
|
-
);
|
|
508
|
-
expect(() => new Parser().parse('RETURN split("a", "b", "c")')).toThrow(
|
|
509
|
-
"Function split expected 2 parameters, but got 3"
|
|
510
|
-
);
|
|
511
|
-
expect(() => new Parser().parse("RETURN size(1, 2)")).toThrow(
|
|
512
|
-
"Function size expected 1 parameters, but got 2"
|
|
513
|
-
);
|
|
514
|
-
expect(() => new Parser().parse("RETURN round(1, 2)")).toThrow(
|
|
515
|
-
"Function round expected 1 parameters, but got 2"
|
|
516
|
-
);
|
|
517
|
-
});
|
|
518
|
-
|
|
519
|
-
test("Test non-well formed statements", () => {
|
|
520
|
-
expect(() => new Parser().parse("return 1 return 1")).toThrow(
|
|
521
|
-
"Only one RETURN statement is allowed"
|
|
522
|
-
);
|
|
523
|
-
expect(() => new Parser().parse("return 1 with 1 as n")).toThrow(
|
|
524
|
-
"Last statement must be a RETURN, WHERE, CALL, CREATE, or DELETE statement"
|
|
525
|
-
);
|
|
526
|
-
});
|
|
527
|
-
|
|
528
|
-
test("Test associative array with backtick string", () => {
|
|
529
|
-
const parser = new Parser();
|
|
530
|
-
const ast = parser.parse("RETURN {`key`: `value`}");
|
|
531
|
-
expect(ast.print()).toBe(
|
|
532
|
-
"ASTNode\n" +
|
|
533
|
-
"- Return\n" +
|
|
534
|
-
"-- Expression\n" +
|
|
535
|
-
"--- AssociativeArray\n" +
|
|
536
|
-
"---- KeyValuePair\n" +
|
|
537
|
-
"----- String (key)\n" +
|
|
538
|
-
"----- Expression\n" +
|
|
539
|
-
"------ Reference (value)"
|
|
540
|
-
);
|
|
541
|
-
});
|
|
542
|
-
|
|
543
|
-
test("Test limit", () => {
|
|
544
|
-
const parser = new Parser();
|
|
545
|
-
const ast = parser.parse("unwind range(1, 10) as n limit 5 return n");
|
|
546
|
-
expect(ast.print()).toBe(
|
|
547
|
-
"ASTNode\n" +
|
|
548
|
-
"- Unwind\n" +
|
|
549
|
-
"-- Expression (n)\n" +
|
|
550
|
-
"--- Function (range)\n" +
|
|
551
|
-
"---- Expression\n" +
|
|
552
|
-
"----- Number (1)\n" +
|
|
553
|
-
"---- Expression\n" +
|
|
554
|
-
"----- Number (10)\n" +
|
|
555
|
-
"- Limit\n" +
|
|
556
|
-
"- Return\n" +
|
|
557
|
-
"-- Expression (n)\n" +
|
|
558
|
-
"--- Reference (n)"
|
|
559
|
-
);
|
|
560
|
-
});
|
|
561
|
-
|
|
562
|
-
test("Test return -2", () => {
|
|
563
|
-
const parser = new Parser();
|
|
564
|
-
const ast = parser.parse("return -2");
|
|
565
|
-
// prettier-ignore
|
|
566
|
-
expect(ast.print()).toBe(
|
|
567
|
-
"ASTNode\n" +
|
|
568
|
-
"- Return\n" +
|
|
569
|
-
"-- Expression\n" +
|
|
570
|
-
"--- Number (-2)"
|
|
571
|
-
);
|
|
572
|
-
});
|
|
573
|
-
|
|
574
|
-
test("Test call operation", () => {
|
|
575
|
-
const parser = new Parser();
|
|
576
|
-
const ast = parser.parse("CALL test() YIELD result RETURN result");
|
|
577
|
-
expect(ast.print()).toBe(
|
|
578
|
-
"ASTNode\n" +
|
|
579
|
-
"- Call\n" +
|
|
580
|
-
"-- Expression (result)\n" +
|
|
581
|
-
"--- Reference (result)\n" +
|
|
582
|
-
"- Return\n" +
|
|
583
|
-
"-- Expression (result)\n" +
|
|
584
|
-
"--- Reference (result)"
|
|
585
|
-
);
|
|
586
|
-
});
|
|
587
|
-
|
|
588
|
-
test("Test f-string", () => {
|
|
589
|
-
const parser = new Parser();
|
|
590
|
-
const ast = parser.parse("with 1 as value RETURN f'Value is: {value}.'");
|
|
591
|
-
expect(ast.print()).toBe(
|
|
592
|
-
"ASTNode\n" +
|
|
593
|
-
"- With\n" +
|
|
594
|
-
"-- Expression (value)\n" +
|
|
595
|
-
"--- Number (1)\n" +
|
|
596
|
-
"- Return\n" +
|
|
597
|
-
"-- Expression\n" +
|
|
598
|
-
"--- FString\n" +
|
|
599
|
-
"---- String (Value is: )\n" +
|
|
600
|
-
"---- Expression\n" +
|
|
601
|
-
"----- Reference (value)\n" +
|
|
602
|
-
"---- String (.)"
|
|
603
|
-
);
|
|
604
|
-
});
|
|
605
|
-
|
|
606
|
-
test("Test create node operation", () => {
|
|
607
|
-
const parser = new Parser();
|
|
608
|
-
const ast = parser.parse(`
|
|
609
|
-
CREATE VIRTUAL (:Person) AS {
|
|
610
|
-
unwind range(1, 3) AS id
|
|
611
|
-
return id, f'Person {id}' AS name
|
|
612
|
-
}
|
|
613
|
-
`);
|
|
614
|
-
// prettier-ignore
|
|
615
|
-
expect(ast.print()).toBe(
|
|
616
|
-
"ASTNode\n" +
|
|
617
|
-
"- CreateNode"
|
|
618
|
-
);
|
|
619
|
-
const create: CreateNode = ast.firstChild() as CreateNode;
|
|
620
|
-
expect(create.node).not.toBeNull();
|
|
621
|
-
expect(create.node!.label).toBe("Person");
|
|
622
|
-
expect(create.statement!.print()).toBe(
|
|
623
|
-
"ASTNode\n" +
|
|
624
|
-
"- Unwind\n" +
|
|
625
|
-
"-- Expression (id)\n" +
|
|
626
|
-
"--- Function (range)\n" +
|
|
627
|
-
"---- Expression\n" +
|
|
628
|
-
"----- Number (1)\n" +
|
|
629
|
-
"---- Expression\n" +
|
|
630
|
-
"----- Number (3)\n" +
|
|
631
|
-
"- Return\n" +
|
|
632
|
-
"-- Expression (id)\n" +
|
|
633
|
-
"--- Reference (id)\n" +
|
|
634
|
-
"-- Expression (name)\n" +
|
|
635
|
-
"--- FString\n" +
|
|
636
|
-
"---- String (Person )\n" +
|
|
637
|
-
"---- Expression\n" +
|
|
638
|
-
"----- Reference (id)\n" +
|
|
639
|
-
"---- String ()"
|
|
640
|
-
);
|
|
641
|
-
});
|
|
642
|
-
|
|
643
|
-
test("Test match operation", () => {
|
|
644
|
-
const parser = new Parser();
|
|
645
|
-
const ast = parser.parse("MATCH (n:Person) RETURN n");
|
|
646
|
-
// prettier-ignore
|
|
647
|
-
expect(ast.print()).toBe(
|
|
648
|
-
"ASTNode\n" +
|
|
649
|
-
"- Match\n" +
|
|
650
|
-
"- Return\n" +
|
|
651
|
-
"-- Expression (n)\n" +
|
|
652
|
-
"--- Reference (n)"
|
|
653
|
-
);
|
|
654
|
-
const match = ast.firstChild() as Match;
|
|
655
|
-
expect(match.patterns[0].startNode).not.toBeNull();
|
|
656
|
-
expect(match.patterns[0].startNode!.label).toBe("Person");
|
|
657
|
-
expect(match.patterns[0].startNode!.identifier).toBe("n");
|
|
658
|
-
});
|
|
659
|
-
|
|
660
|
-
test("Test create relationship operation", () => {
|
|
661
|
-
const parser = new Parser();
|
|
662
|
-
const ast = parser.parse(`
|
|
663
|
-
CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
|
|
664
|
-
unwind [
|
|
665
|
-
{from_id: 1, to_id: 2, since: '2020-01-01'},
|
|
666
|
-
{from_id: 2, to_id: 3, since: '2021-01-01'}
|
|
667
|
-
] AS pair
|
|
668
|
-
return pair.from_id AS from, pair.to_id AS to, pair.since AS since
|
|
669
|
-
}
|
|
670
|
-
`);
|
|
671
|
-
// prettier-ignore
|
|
672
|
-
expect(ast.print()).toBe(
|
|
673
|
-
"ASTNode\n" +
|
|
674
|
-
"- CreateRelationship"
|
|
675
|
-
);
|
|
676
|
-
const create = ast.firstChild() as CreateRelationship;
|
|
677
|
-
expect(create.relationship).not.toBeNull();
|
|
678
|
-
expect(create.relationship!.type).toBe("KNOWS");
|
|
679
|
-
expect(create.statement!.print()).toBe(
|
|
680
|
-
"ASTNode\n" +
|
|
681
|
-
"- Unwind\n" +
|
|
682
|
-
"-- Expression (pair)\n" +
|
|
683
|
-
"--- JSONArray\n" +
|
|
684
|
-
"---- Expression\n" +
|
|
685
|
-
"----- AssociativeArray\n" +
|
|
686
|
-
"------ KeyValuePair\n" +
|
|
687
|
-
"------- String (from_id)\n" +
|
|
688
|
-
"------- Expression\n" +
|
|
689
|
-
"-------- Number (1)\n" +
|
|
690
|
-
"------ KeyValuePair\n" +
|
|
691
|
-
"------- String (to_id)\n" +
|
|
692
|
-
"------- Expression\n" +
|
|
693
|
-
"-------- Number (2)\n" +
|
|
694
|
-
"------ KeyValuePair\n" +
|
|
695
|
-
"------- String (since)\n" +
|
|
696
|
-
"------- Expression\n" +
|
|
697
|
-
"-------- String (2020-01-01)\n" +
|
|
698
|
-
"---- Expression\n" +
|
|
699
|
-
"----- AssociativeArray\n" +
|
|
700
|
-
"------ KeyValuePair\n" +
|
|
701
|
-
"------- String (from_id)\n" +
|
|
702
|
-
"------- Expression\n" +
|
|
703
|
-
"-------- Number (2)\n" +
|
|
704
|
-
"------ KeyValuePair\n" +
|
|
705
|
-
"------- String (to_id)\n" +
|
|
706
|
-
"------- Expression\n" +
|
|
707
|
-
"-------- Number (3)\n" +
|
|
708
|
-
"------ KeyValuePair\n" +
|
|
709
|
-
"------- String (since)\n" +
|
|
710
|
-
"------- Expression\n" +
|
|
711
|
-
"-------- String (2021-01-01)\n" +
|
|
712
|
-
"- Return\n" +
|
|
713
|
-
"-- Expression (from)\n" +
|
|
714
|
-
"--- Lookup\n" +
|
|
715
|
-
"---- Identifier (from_id)\n" +
|
|
716
|
-
"---- Reference (pair)\n" +
|
|
717
|
-
"-- Expression (to)\n" +
|
|
718
|
-
"--- Lookup\n" +
|
|
719
|
-
"---- Identifier (to_id)\n" +
|
|
720
|
-
"---- Reference (pair)\n" +
|
|
721
|
-
"-- Expression (since)\n" +
|
|
722
|
-
"--- Lookup\n" +
|
|
723
|
-
"---- Identifier (since)\n" +
|
|
724
|
-
"---- Reference (pair)"
|
|
725
|
-
);
|
|
726
|
-
});
|
|
727
|
-
|
|
728
|
-
test("Match with graph pattern including relationships", () => {
|
|
729
|
-
const parser = new Parser();
|
|
730
|
-
const ast = parser.parse("MATCH (a:Person)-[:KNOWS]-(b:Person) RETURN a, b");
|
|
731
|
-
// prettier-ignore
|
|
732
|
-
expect(ast.print()).toBe(
|
|
733
|
-
"ASTNode\n" +
|
|
734
|
-
"- Match\n" +
|
|
735
|
-
"- Return\n" +
|
|
736
|
-
"-- Expression (a)\n" +
|
|
737
|
-
"--- Reference (a)\n" +
|
|
738
|
-
"-- Expression (b)\n" +
|
|
739
|
-
"--- Reference (b)"
|
|
740
|
-
);
|
|
741
|
-
const match = ast.firstChild() as Match;
|
|
742
|
-
expect(match.patterns[0].chain.length).toBe(3);
|
|
743
|
-
const source = match.patterns[0].chain[0] as Node;
|
|
744
|
-
const relationship = match.patterns[0].chain[1] as Relationship;
|
|
745
|
-
const target = match.patterns[0].chain[2] as Node;
|
|
746
|
-
expect(source.identifier).toBe("a");
|
|
747
|
-
expect(source.label).toBe("Person");
|
|
748
|
-
expect(relationship.type).toBe("KNOWS");
|
|
749
|
-
expect(target.identifier).toBe("b");
|
|
750
|
-
expect(target.label).toBe("Person");
|
|
751
|
-
});
|
|
752
|
-
|
|
753
|
-
test("Match with ORed relationship types", () => {
|
|
754
|
-
const parser = new Parser();
|
|
755
|
-
const ast = parser.parse("MATCH (a:Person)-[:KNOWS|FOLLOWS]->(b:Person) RETURN a, b");
|
|
756
|
-
const match = ast.firstChild() as Match;
|
|
757
|
-
expect(match.patterns[0].chain.length).toBe(3);
|
|
758
|
-
const relationship = match.patterns[0].chain[1] as Relationship;
|
|
759
|
-
expect(relationship.types).toEqual(["KNOWS", "FOLLOWS"]);
|
|
760
|
-
expect(relationship.type).toBe("KNOWS");
|
|
761
|
-
});
|
|
762
|
-
|
|
763
|
-
test("Match with ORed relationship types with optional colons", () => {
|
|
764
|
-
const parser = new Parser();
|
|
765
|
-
const ast = parser.parse("MATCH (a:Person)-[:KNOWS|:FOLLOWS|:LIKES]->(b:Person) RETURN a, b");
|
|
766
|
-
const match = ast.firstChild() as Match;
|
|
767
|
-
const relationship = match.patterns[0].chain[1] as Relationship;
|
|
768
|
-
expect(relationship.types).toEqual(["KNOWS", "FOLLOWS", "LIKES"]);
|
|
769
|
-
});
|
|
770
|
-
|
|
771
|
-
test("Match with ORed relationship types and variable", () => {
|
|
772
|
-
const parser = new Parser();
|
|
773
|
-
const ast = parser.parse("MATCH (a:Person)-[r:KNOWS|FOLLOWS]->(b:Person) RETURN a, r, b");
|
|
774
|
-
const match = ast.firstChild() as Match;
|
|
775
|
-
const relationship = match.patterns[0].chain[1] as Relationship;
|
|
776
|
-
expect(relationship.identifier).toBe("r");
|
|
777
|
-
expect(relationship.types).toEqual(["KNOWS", "FOLLOWS"]);
|
|
778
|
-
});
|
|
779
|
-
|
|
780
|
-
test("Match with ORed relationship types and hops", () => {
|
|
781
|
-
const parser = new Parser();
|
|
782
|
-
const ast = parser.parse("MATCH (a:Person)-[:KNOWS|FOLLOWS*1..3]->(b:Person) RETURN a, b");
|
|
783
|
-
const match = ast.firstChild() as Match;
|
|
784
|
-
const relationship = match.patterns[0].chain[1] as Relationship;
|
|
785
|
-
expect(relationship.types).toEqual(["KNOWS", "FOLLOWS"]);
|
|
786
|
-
expect(relationship.hops!.min).toBe(1);
|
|
787
|
-
expect(relationship.hops!.max).toBe(3);
|
|
788
|
-
});
|
|
789
|
-
|
|
790
|
-
test("Test not equal operator", () => {
|
|
791
|
-
const parser = new Parser();
|
|
792
|
-
const ast = parser.parse("RETURN 1 <> 2");
|
|
793
|
-
expect(ast.print()).toBe(
|
|
794
|
-
"ASTNode\n" +
|
|
795
|
-
"- Return\n" +
|
|
796
|
-
"-- Expression\n" +
|
|
797
|
-
"--- NotEquals\n" +
|
|
798
|
-
"---- Number (1)\n" +
|
|
799
|
-
"---- Number (2)"
|
|
800
|
-
);
|
|
801
|
-
});
|
|
802
|
-
|
|
803
|
-
test("Test equal operator", () => {
|
|
804
|
-
const parser = new Parser();
|
|
805
|
-
const ast = parser.parse("RETURN 1 = 2");
|
|
806
|
-
expect(ast.print()).toBe(
|
|
807
|
-
"ASTNode\n" +
|
|
808
|
-
"- Return\n" +
|
|
809
|
-
"-- Expression\n" +
|
|
810
|
-
"--- Equals\n" +
|
|
811
|
-
"---- Number (1)\n" +
|
|
812
|
-
"---- Number (2)"
|
|
813
|
-
);
|
|
814
|
-
});
|
|
815
|
-
|
|
816
|
-
test("Test not operator", () => {
|
|
817
|
-
const parser = new Parser();
|
|
818
|
-
const ast = parser.parse("RETURN NOT true");
|
|
819
|
-
// prettier-ignore
|
|
820
|
-
expect(ast.print()).toBe(
|
|
821
|
-
"ASTNode\n" +
|
|
822
|
-
"- Return\n" +
|
|
823
|
-
"-- Expression\n" +
|
|
824
|
-
"--- Not\n" +
|
|
825
|
-
"---- Expression\n" +
|
|
826
|
-
"----- Boolean"
|
|
827
|
-
);
|
|
828
|
-
});
|
|
829
|
-
|
|
830
|
-
test("Parse relationship with hops", () => {
|
|
831
|
-
const parser = new Parser();
|
|
832
|
-
const ast = parser.parse("MATCH (a:Test)-[:KNOWS*1..3]->(b:Test) RETURN a, b");
|
|
833
|
-
// prettier-ignore
|
|
834
|
-
expect(ast.print()).toBe(
|
|
835
|
-
"ASTNode\n" +
|
|
836
|
-
"- Match\n" +
|
|
837
|
-
"- Return\n" +
|
|
838
|
-
"-- Expression (a)\n" +
|
|
839
|
-
"--- Reference (a)\n" +
|
|
840
|
-
"-- Expression (b)\n" +
|
|
841
|
-
"--- Reference (b)"
|
|
842
|
-
);
|
|
843
|
-
const match = ast.firstChild() as Match;
|
|
844
|
-
expect(match.patterns[0].chain.length).toBe(3);
|
|
845
|
-
const source = match.patterns[0].chain[0] as Node;
|
|
846
|
-
const relationship = match.patterns[0].chain[1] as Relationship;
|
|
847
|
-
const target = match.patterns[0].chain[2] as Node;
|
|
848
|
-
expect(source.identifier).toBe("a");
|
|
849
|
-
expect(relationship.type).toBe("KNOWS");
|
|
850
|
-
expect(relationship.hops).not.toBeNull();
|
|
851
|
-
expect(relationship.hops!.min).toBe(1);
|
|
852
|
-
expect(relationship.hops!.max).toBe(3);
|
|
853
|
-
expect(target.identifier).toBe("b");
|
|
854
|
-
});
|
|
855
|
-
|
|
856
|
-
test("Parse statement with graph pattern in where clause", () => {
|
|
857
|
-
const parser = new Parser();
|
|
858
|
-
const ast = parser.parse("MATCH (a:Person) WHERE (a)-[:KNOWS]->(:Person) RETURN a");
|
|
859
|
-
// prettier-ignore
|
|
860
|
-
expect(ast.print()).toBe(
|
|
861
|
-
"ASTNode\n" +
|
|
862
|
-
"- Match\n" +
|
|
863
|
-
"- Where\n" +
|
|
864
|
-
"-- Expression\n" +
|
|
865
|
-
"--- PatternExpression\n" +
|
|
866
|
-
"- Return\n" +
|
|
867
|
-
"-- Expression (a)\n" +
|
|
868
|
-
"--- Reference (a)"
|
|
869
|
-
);
|
|
870
|
-
const match = ast.firstChild() as Match;
|
|
871
|
-
expect(match.patterns[0].startNode).not.toBeNull();
|
|
872
|
-
expect(match.patterns[0].startNode!.identifier).toBe("a");
|
|
873
|
-
const where = match.next as any;
|
|
874
|
-
const pattern = where.firstChild().firstChild() as any;
|
|
875
|
-
expect(pattern.chain.length).toBe(3);
|
|
876
|
-
const source = pattern.chain[0] as NodeReference;
|
|
877
|
-
const relationship = pattern.chain[1] as Relationship;
|
|
878
|
-
const target = pattern.chain[2] as Node;
|
|
879
|
-
expect((source.reference as Node)?.identifier).toBe("a");
|
|
880
|
-
expect(relationship.type).toBe("KNOWS");
|
|
881
|
-
expect(target.label).toBe("Person");
|
|
882
|
-
});
|
|
883
|
-
|
|
884
|
-
test("Test check pattern expression without NodeReference", () => {
|
|
885
|
-
const parser = new Parser();
|
|
886
|
-
// Should throw an error because pattern does not start with NodeReference
|
|
887
|
-
expect(() => {
|
|
888
|
-
parser.parse("MATCH (a:Person) WHERE (:Person)-[:KNOWS]->(:Person) RETURN a");
|
|
889
|
-
}).toThrow("PatternExpression must contain at least one NodeReference");
|
|
890
|
-
});
|
|
891
|
-
|
|
892
|
-
test("Test node with properties", () => {
|
|
893
|
-
const parser = new Parser();
|
|
894
|
-
const ast = parser.parse("MATCH (a:Person{value: 'hello'}) return a");
|
|
895
|
-
// prettier-ignore
|
|
896
|
-
expect(ast.print()).toBe(
|
|
897
|
-
"ASTNode\n" +
|
|
898
|
-
"- Match\n" +
|
|
899
|
-
"- Return\n" +
|
|
900
|
-
"-- Expression (a)\n" +
|
|
901
|
-
"--- Reference (a)"
|
|
902
|
-
);
|
|
903
|
-
const match: Match = ast.firstChild() as Match;
|
|
904
|
-
const node: Node = match.patterns[0].chain[0] as Node;
|
|
905
|
-
expect(node.properties.get("value")?.value()).toBe("hello");
|
|
906
|
-
});
|
|
907
|
-
|
|
908
|
-
test("Test WHERE in CREATE VIRTUAL sub-query", () => {
|
|
909
|
-
const parser = new Parser();
|
|
910
|
-
const ast = parser.parse(`
|
|
911
|
-
CREATE VIRTUAL (:Email)-[:HAS_ATTACHMENT]-(:File) AS {
|
|
912
|
-
LOAD JSON FROM '/data/emails.json' AS email
|
|
913
|
-
WHERE email.hasAttachments = true
|
|
914
|
-
UNWIND email.attachments AS fileId
|
|
915
|
-
RETURN email.id AS left_id, fileId AS right_id
|
|
916
|
-
}
|
|
917
|
-
`);
|
|
918
|
-
const create = ast.firstChild() as CreateRelationship;
|
|
919
|
-
expect(create.relationship).not.toBeNull();
|
|
920
|
-
expect(create.relationship!.type).toBe("HAS_ATTACHMENT");
|
|
921
|
-
expect(create.statement).not.toBeNull();
|
|
922
|
-
});
|
|
923
|
-
|
|
924
|
-
test("Test relationship with properties", () => {
|
|
925
|
-
const parser = new Parser();
|
|
926
|
-
const ast = parser.parse("MATCH (:Person)-[r:LIKES{since: 2022}]->(:Food) return a");
|
|
927
|
-
// prettier-ignore
|
|
928
|
-
expect(ast.print()).toBe(
|
|
929
|
-
"ASTNode\n" +
|
|
930
|
-
"- Match\n" +
|
|
931
|
-
"- Return\n" +
|
|
932
|
-
"-- Expression (a)\n" +
|
|
933
|
-
"--- Reference (a)"
|
|
934
|
-
);
|
|
935
|
-
const match: Match = ast.firstChild() as Match;
|
|
936
|
-
const relationship: Relationship = match.patterns[0].chain[1] as Relationship;
|
|
937
|
-
expect(relationship.properties.get("since")?.value()).toBe(2022);
|
|
938
|
-
});
|
|
939
|
-
|
|
940
|
-
test("Test node reference with label creates NodeReference instead of new node", () => {
|
|
941
|
-
const parser = new Parser();
|
|
942
|
-
const ast = parser.parse("MATCH (n:Person)-[:KNOWS]->(n:Person) RETURN n");
|
|
943
|
-
const match: Match = ast.firstChild() as Match;
|
|
944
|
-
const firstNode = match.patterns[0].chain[0] as Node;
|
|
945
|
-
const secondNode = match.patterns[0].chain[2] as NodeReference;
|
|
946
|
-
expect(firstNode.identifier).toBe("n");
|
|
947
|
-
expect(firstNode.label).toBe("Person");
|
|
948
|
-
expect(secondNode).toBeInstanceOf(NodeReference);
|
|
949
|
-
expect((secondNode.reference! as Node).identifier).toBe("n");
|
|
950
|
-
expect(secondNode.label).toBe("Person");
|
|
951
|
-
});
|
|
952
|
-
|
|
953
|
-
test("Test relationship reference with type creates RelationshipReference instead of new relationship", () => {
|
|
954
|
-
const parser = new Parser();
|
|
955
|
-
const ast = parser.parse(
|
|
956
|
-
"MATCH (a:Person)-[r:KNOWS]->(b:Person)-[r:KNOWS]->(c:Person) RETURN a, b, c"
|
|
957
|
-
);
|
|
958
|
-
const match: Match = ast.firstChild() as Match;
|
|
959
|
-
const firstRel = match.patterns[0].chain[1] as Relationship;
|
|
960
|
-
const secondRel = match.patterns[0].chain[3] as RelationshipReference;
|
|
961
|
-
expect(firstRel.identifier).toBe("r");
|
|
962
|
-
expect(firstRel.type).toBe("KNOWS");
|
|
963
|
-
expect(secondRel).toBeInstanceOf(RelationshipReference);
|
|
964
|
-
expect(secondRel.type).toBe("KNOWS");
|
|
965
|
-
});
|
|
966
|
-
|
|
967
|
-
test("Test WHERE with IN list check", () => {
|
|
968
|
-
const parser = new Parser();
|
|
969
|
-
const ast = parser.parse("with 1 as n where n IN [1, 2, 3] return n");
|
|
970
|
-
// prettier-ignore
|
|
971
|
-
expect(ast.print()).toBe(
|
|
972
|
-
"ASTNode\n" +
|
|
973
|
-
"- With\n" +
|
|
974
|
-
"-- Expression (n)\n" +
|
|
975
|
-
"--- Number (1)\n" +
|
|
976
|
-
"- Where\n" +
|
|
977
|
-
"-- Expression\n" +
|
|
978
|
-
"--- In\n" +
|
|
979
|
-
"---- Reference (n)\n" +
|
|
980
|
-
"---- JSONArray\n" +
|
|
981
|
-
"----- Expression\n" +
|
|
982
|
-
"------ Number (1)\n" +
|
|
983
|
-
"----- Expression\n" +
|
|
984
|
-
"------ Number (2)\n" +
|
|
985
|
-
"----- Expression\n" +
|
|
986
|
-
"------ Number (3)\n" +
|
|
987
|
-
"- Return\n" +
|
|
988
|
-
"-- Expression (n)\n" +
|
|
989
|
-
"--- Reference (n)"
|
|
990
|
-
);
|
|
991
|
-
});
|
|
992
|
-
|
|
993
|
-
test("Test WHERE with NOT IN list check", () => {
|
|
994
|
-
const parser = new Parser();
|
|
995
|
-
const ast = parser.parse("with 4 as n where n NOT IN [1, 2, 3] return n");
|
|
996
|
-
// prettier-ignore
|
|
997
|
-
expect(ast.print()).toBe(
|
|
998
|
-
"ASTNode\n" +
|
|
999
|
-
"- With\n" +
|
|
1000
|
-
"-- Expression (n)\n" +
|
|
1001
|
-
"--- Number (4)\n" +
|
|
1002
|
-
"- Where\n" +
|
|
1003
|
-
"-- Expression\n" +
|
|
1004
|
-
"--- NotIn\n" +
|
|
1005
|
-
"---- Reference (n)\n" +
|
|
1006
|
-
"---- JSONArray\n" +
|
|
1007
|
-
"----- Expression\n" +
|
|
1008
|
-
"------ Number (1)\n" +
|
|
1009
|
-
"----- Expression\n" +
|
|
1010
|
-
"------ Number (2)\n" +
|
|
1011
|
-
"----- Expression\n" +
|
|
1012
|
-
"------ Number (3)\n" +
|
|
1013
|
-
"- Return\n" +
|
|
1014
|
-
"-- Expression (n)\n" +
|
|
1015
|
-
"--- Reference (n)"
|
|
1016
|
-
);
|
|
1017
|
-
});
|
|
1018
|
-
|
|
1019
|
-
test("Test WHERE with CONTAINS", () => {
|
|
1020
|
-
const parser = new Parser();
|
|
1021
|
-
const ast = parser.parse("with 'hello' as s where s CONTAINS 'ell' return s");
|
|
1022
|
-
// prettier-ignore
|
|
1023
|
-
expect(ast.print()).toBe(
|
|
1024
|
-
"ASTNode\n" +
|
|
1025
|
-
"- With\n" +
|
|
1026
|
-
"-- Expression (s)\n" +
|
|
1027
|
-
"--- String (hello)\n" +
|
|
1028
|
-
"- Where\n" +
|
|
1029
|
-
"-- Expression\n" +
|
|
1030
|
-
"--- Contains\n" +
|
|
1031
|
-
"---- Reference (s)\n" +
|
|
1032
|
-
"---- String (ell)\n" +
|
|
1033
|
-
"- Return\n" +
|
|
1034
|
-
"-- Expression (s)\n" +
|
|
1035
|
-
"--- Reference (s)"
|
|
1036
|
-
);
|
|
1037
|
-
});
|
|
1038
|
-
|
|
1039
|
-
test("Test WHERE with NOT CONTAINS", () => {
|
|
1040
|
-
const parser = new Parser();
|
|
1041
|
-
const ast = parser.parse("with 'hello' as s where s NOT CONTAINS 'xyz' return s");
|
|
1042
|
-
// prettier-ignore
|
|
1043
|
-
expect(ast.print()).toBe(
|
|
1044
|
-
"ASTNode\n" +
|
|
1045
|
-
"- With\n" +
|
|
1046
|
-
"-- Expression (s)\n" +
|
|
1047
|
-
"--- String (hello)\n" +
|
|
1048
|
-
"- Where\n" +
|
|
1049
|
-
"-- Expression\n" +
|
|
1050
|
-
"--- NotContains\n" +
|
|
1051
|
-
"---- Reference (s)\n" +
|
|
1052
|
-
"---- String (xyz)\n" +
|
|
1053
|
-
"- Return\n" +
|
|
1054
|
-
"-- Expression (s)\n" +
|
|
1055
|
-
"--- Reference (s)"
|
|
1056
|
-
);
|
|
1057
|
-
});
|
|
1058
|
-
|
|
1059
|
-
test("Test WHERE with STARTS WITH", () => {
|
|
1060
|
-
const parser = new Parser();
|
|
1061
|
-
const ast = parser.parse("with 'hello' as s where s STARTS WITH 'hel' return s");
|
|
1062
|
-
// prettier-ignore
|
|
1063
|
-
expect(ast.print()).toBe(
|
|
1064
|
-
"ASTNode\n" +
|
|
1065
|
-
"- With\n" +
|
|
1066
|
-
"-- Expression (s)\n" +
|
|
1067
|
-
"--- String (hello)\n" +
|
|
1068
|
-
"- Where\n" +
|
|
1069
|
-
"-- Expression\n" +
|
|
1070
|
-
"--- StartsWith\n" +
|
|
1071
|
-
"---- Reference (s)\n" +
|
|
1072
|
-
"---- String (hel)\n" +
|
|
1073
|
-
"- Return\n" +
|
|
1074
|
-
"-- Expression (s)\n" +
|
|
1075
|
-
"--- Reference (s)"
|
|
1076
|
-
);
|
|
1077
|
-
});
|
|
1078
|
-
|
|
1079
|
-
test("Test WHERE with NOT STARTS WITH", () => {
|
|
1080
|
-
const parser = new Parser();
|
|
1081
|
-
const ast = parser.parse("with 'hello' as s where s NOT STARTS WITH 'xyz' return s");
|
|
1082
|
-
// prettier-ignore
|
|
1083
|
-
expect(ast.print()).toBe(
|
|
1084
|
-
"ASTNode\n" +
|
|
1085
|
-
"- With\n" +
|
|
1086
|
-
"-- Expression (s)\n" +
|
|
1087
|
-
"--- String (hello)\n" +
|
|
1088
|
-
"- Where\n" +
|
|
1089
|
-
"-- Expression\n" +
|
|
1090
|
-
"--- NotStartsWith\n" +
|
|
1091
|
-
"---- Reference (s)\n" +
|
|
1092
|
-
"---- String (xyz)\n" +
|
|
1093
|
-
"- Return\n" +
|
|
1094
|
-
"-- Expression (s)\n" +
|
|
1095
|
-
"--- Reference (s)"
|
|
1096
|
-
);
|
|
1097
|
-
});
|
|
1098
|
-
|
|
1099
|
-
test("Test WHERE with ENDS WITH", () => {
|
|
1100
|
-
const parser = new Parser();
|
|
1101
|
-
const ast = parser.parse("with 'hello' as s where s ENDS WITH 'llo' return s");
|
|
1102
|
-
// prettier-ignore
|
|
1103
|
-
expect(ast.print()).toBe(
|
|
1104
|
-
"ASTNode\n" +
|
|
1105
|
-
"- With\n" +
|
|
1106
|
-
"-- Expression (s)\n" +
|
|
1107
|
-
"--- String (hello)\n" +
|
|
1108
|
-
"- Where\n" +
|
|
1109
|
-
"-- Expression\n" +
|
|
1110
|
-
"--- EndsWith\n" +
|
|
1111
|
-
"---- Reference (s)\n" +
|
|
1112
|
-
"---- String (llo)\n" +
|
|
1113
|
-
"- Return\n" +
|
|
1114
|
-
"-- Expression (s)\n" +
|
|
1115
|
-
"--- Reference (s)"
|
|
1116
|
-
);
|
|
1117
|
-
});
|
|
1118
|
-
|
|
1119
|
-
test("Test WHERE with NOT ENDS WITH", () => {
|
|
1120
|
-
const parser = new Parser();
|
|
1121
|
-
const ast = parser.parse("with 'hello' as s where s NOT ENDS WITH 'xyz' return s");
|
|
1122
|
-
// prettier-ignore
|
|
1123
|
-
expect(ast.print()).toBe(
|
|
1124
|
-
"ASTNode\n" +
|
|
1125
|
-
"- With\n" +
|
|
1126
|
-
"-- Expression (s)\n" +
|
|
1127
|
-
"--- String (hello)\n" +
|
|
1128
|
-
"- Where\n" +
|
|
1129
|
-
"-- Expression\n" +
|
|
1130
|
-
"--- NotEndsWith\n" +
|
|
1131
|
-
"---- Reference (s)\n" +
|
|
1132
|
-
"---- String (xyz)\n" +
|
|
1133
|
-
"- Return\n" +
|
|
1134
|
-
"-- Expression (s)\n" +
|
|
1135
|
-
"--- Reference (s)"
|
|
1136
|
-
);
|
|
1137
|
-
});
|
|
1138
|
-
|
|
1139
|
-
test("Test parenthesized expression with addition", () => {
|
|
1140
|
-
const parser = new Parser();
|
|
1141
|
-
const ast = parser.parse("WITH 1 AS n RETURN (n + 2)");
|
|
1142
|
-
// prettier-ignore
|
|
1143
|
-
expect(ast.print()).toBe(
|
|
1144
|
-
"ASTNode\n" +
|
|
1145
|
-
"- With\n" +
|
|
1146
|
-
"-- Expression (n)\n" +
|
|
1147
|
-
"--- Number (1)\n" +
|
|
1148
|
-
"- Return\n" +
|
|
1149
|
-
"-- Expression\n" +
|
|
1150
|
-
"--- Expression\n" +
|
|
1151
|
-
"---- Add\n" +
|
|
1152
|
-
"----- Reference (n)\n" +
|
|
1153
|
-
"----- Number (2)"
|
|
1154
|
-
);
|
|
1155
|
-
});
|
|
1156
|
-
|
|
1157
|
-
test("Test parenthesized expression with property access", () => {
|
|
1158
|
-
const parser = new Parser();
|
|
1159
|
-
const ast = parser.parse("WITH {a: 1} AS obj RETURN (obj.a)");
|
|
1160
|
-
// prettier-ignore
|
|
1161
|
-
expect(ast.print()).toBe(
|
|
1162
|
-
"ASTNode\n" +
|
|
1163
|
-
"- With\n" +
|
|
1164
|
-
"-- Expression (obj)\n" +
|
|
1165
|
-
"--- AssociativeArray\n" +
|
|
1166
|
-
"---- KeyValuePair\n" +
|
|
1167
|
-
"----- String (a)\n" +
|
|
1168
|
-
"----- Expression\n" +
|
|
1169
|
-
"------ Number (1)\n" +
|
|
1170
|
-
"- Return\n" +
|
|
1171
|
-
"-- Expression\n" +
|
|
1172
|
-
"--- Expression\n" +
|
|
1173
|
-
"---- Lookup\n" +
|
|
1174
|
-
"----- Identifier (a)\n" +
|
|
1175
|
-
"----- Reference (obj)"
|
|
1176
|
-
);
|
|
1177
|
-
});
|
|
1178
|
-
|
|
1179
|
-
test("Test parenthesized expression with multiplication", () => {
|
|
1180
|
-
const parser = new Parser();
|
|
1181
|
-
const ast = parser.parse("WITH 5 AS x RETURN (x * 3)");
|
|
1182
|
-
// prettier-ignore
|
|
1183
|
-
expect(ast.print()).toBe(
|
|
1184
|
-
"ASTNode\n" +
|
|
1185
|
-
"- With\n" +
|
|
1186
|
-
"-- Expression (x)\n" +
|
|
1187
|
-
"--- Number (5)\n" +
|
|
1188
|
-
"- Return\n" +
|
|
1189
|
-
"-- Expression\n" +
|
|
1190
|
-
"--- Expression\n" +
|
|
1191
|
-
"---- Multiply\n" +
|
|
1192
|
-
"----- Reference (x)\n" +
|
|
1193
|
-
"----- Number (3)"
|
|
1194
|
-
);
|
|
1195
|
-
});
|
|
1196
|
-
|
|
1197
|
-
test("Test optional match operation", () => {
|
|
1198
|
-
const parser = new Parser();
|
|
1199
|
-
const ast = parser.parse("OPTIONAL MATCH (n:Person) RETURN n");
|
|
1200
|
-
// prettier-ignore
|
|
1201
|
-
expect(ast.print()).toBe(
|
|
1202
|
-
"ASTNode\n" +
|
|
1203
|
-
"- OptionalMatch\n" +
|
|
1204
|
-
"- Return\n" +
|
|
1205
|
-
"-- Expression (n)\n" +
|
|
1206
|
-
"--- Reference (n)"
|
|
1207
|
-
);
|
|
1208
|
-
const match = ast.firstChild() as Match;
|
|
1209
|
-
expect(match.optional).toBe(true);
|
|
1210
|
-
expect(match.patterns[0].startNode).not.toBeNull();
|
|
1211
|
-
expect(match.patterns[0].startNode!.label).toBe("Person");
|
|
1212
|
-
expect(match.patterns[0].startNode!.identifier).toBe("n");
|
|
1213
|
-
});
|
|
1214
|
-
|
|
1215
|
-
test("Optional match with relationships", () => {
|
|
1216
|
-
const parser = new Parser();
|
|
1217
|
-
const ast = parser.parse("OPTIONAL MATCH (a:Person)-[:KNOWS]-(b:Person) RETURN a, b");
|
|
1218
|
-
// prettier-ignore
|
|
1219
|
-
expect(ast.print()).toBe(
|
|
1220
|
-
"ASTNode\n" +
|
|
1221
|
-
"- OptionalMatch\n" +
|
|
1222
|
-
"- Return\n" +
|
|
1223
|
-
"-- Expression (a)\n" +
|
|
1224
|
-
"--- Reference (a)\n" +
|
|
1225
|
-
"-- Expression (b)\n" +
|
|
1226
|
-
"--- Reference (b)"
|
|
1227
|
-
);
|
|
1228
|
-
const match = ast.firstChild() as Match;
|
|
1229
|
-
expect(match.optional).toBe(true);
|
|
1230
|
-
expect(match.patterns[0].chain.length).toBe(3);
|
|
1231
|
-
const source = match.patterns[0].chain[0] as Node;
|
|
1232
|
-
const relationship = match.patterns[0].chain[1] as Relationship;
|
|
1233
|
-
const target = match.patterns[0].chain[2] as Node;
|
|
1234
|
-
expect(source.identifier).toBe("a");
|
|
1235
|
-
expect(source.label).toBe("Person");
|
|
1236
|
-
expect(relationship.type).toBe("KNOWS");
|
|
1237
|
-
expect(target.identifier).toBe("b");
|
|
1238
|
-
expect(target.label).toBe("Person");
|
|
1239
|
-
});
|
|
1240
|
-
|
|
1241
|
-
test("Match followed by optional match", () => {
|
|
1242
|
-
const parser = new Parser();
|
|
1243
|
-
const ast = parser.parse("MATCH (a:Person) OPTIONAL MATCH (a)-[:KNOWS]-(b:Person) RETURN a, b");
|
|
1244
|
-
// prettier-ignore
|
|
1245
|
-
expect(ast.print()).toBe(
|
|
1246
|
-
"ASTNode\n" +
|
|
1247
|
-
"- Match\n" +
|
|
1248
|
-
"- OptionalMatch\n" +
|
|
1249
|
-
"- Return\n" +
|
|
1250
|
-
"-- Expression (a)\n" +
|
|
1251
|
-
"--- Reference (a)\n" +
|
|
1252
|
-
"-- Expression (b)\n" +
|
|
1253
|
-
"--- Reference (b)"
|
|
1254
|
-
);
|
|
1255
|
-
const match = ast.firstChild() as Match;
|
|
1256
|
-
expect(match.optional).toBe(false);
|
|
1257
|
-
const optionalMatch = match.next as Match;
|
|
1258
|
-
expect(optionalMatch.optional).toBe(true);
|
|
1259
|
-
});
|
|
1260
|
-
|
|
1261
|
-
test("Regular match is not optional", () => {
|
|
1262
|
-
const parser = new Parser();
|
|
1263
|
-
const ast = parser.parse("MATCH (n:Person) RETURN n");
|
|
1264
|
-
const match = ast.firstChild() as Match;
|
|
1265
|
-
expect(match.optional).toBe(false);
|
|
1266
|
-
});
|
|
1267
|
-
|
|
1268
|
-
test("OPTIONAL without MATCH throws error", () => {
|
|
1269
|
-
const parser = new Parser();
|
|
1270
|
-
expect(() => parser.parse("OPTIONAL RETURN 1")).toThrow("Expected MATCH after OPTIONAL");
|
|
1271
|
-
});
|
|
1272
|
-
|
|
1273
|
-
// ORDER BY expression tests
|
|
1274
|
-
|
|
1275
|
-
test("ORDER BY with simple identifier parses correctly", () => {
|
|
1276
|
-
const parser = new Parser();
|
|
1277
|
-
const ast = parser.parse("unwind [1, 2] as x return x order by x");
|
|
1278
|
-
expect(ast).toBeDefined();
|
|
1279
|
-
});
|
|
1280
|
-
|
|
1281
|
-
test("ORDER BY with property access parses correctly", () => {
|
|
1282
|
-
const parser = new Parser();
|
|
1283
|
-
const ast = parser.parse(
|
|
1284
|
-
"unwind [{name: 'Bob'}, {name: 'Alice'}] as person return person.name as name order by person.name asc"
|
|
1285
|
-
);
|
|
1286
|
-
expect(ast).toBeDefined();
|
|
1287
|
-
});
|
|
1288
|
-
|
|
1289
|
-
test("ORDER BY with function call parses correctly", () => {
|
|
1290
|
-
const parser = new Parser();
|
|
1291
|
-
const ast = parser.parse(
|
|
1292
|
-
"unwind ['HELLO', 'WORLD'] as word return word order by toLower(word) asc"
|
|
1293
|
-
);
|
|
1294
|
-
expect(ast).toBeDefined();
|
|
1295
|
-
});
|
|
1296
|
-
|
|
1297
|
-
test("ORDER BY with nested function calls parses correctly", () => {
|
|
1298
|
-
const parser = new Parser();
|
|
1299
|
-
const ast = parser.parse(
|
|
1300
|
-
"unwind ['Alice', 'Bob'] as name return name order by string_distance(toLower(name), toLower('alice')) asc"
|
|
1301
|
-
);
|
|
1302
|
-
expect(ast).toBeDefined();
|
|
1303
|
-
});
|
|
1304
|
-
|
|
1305
|
-
test("ORDER BY with arithmetic expression parses correctly", () => {
|
|
1306
|
-
const parser = new Parser();
|
|
1307
|
-
const ast = parser.parse(
|
|
1308
|
-
"unwind [{a: 3, b: 1}, {a: 1, b: 5}] as item return item.a as a, item.b as b order by item.a + item.b desc"
|
|
1309
|
-
);
|
|
1310
|
-
expect(ast).toBeDefined();
|
|
1311
|
-
});
|
|
1312
|
-
|
|
1313
|
-
test("ORDER BY with multiple expression fields parses correctly", () => {
|
|
1314
|
-
const parser = new Parser();
|
|
1315
|
-
const ast = parser.parse(
|
|
1316
|
-
"unwind [{a: 1, b: 2}] as item return item.a as a, item.b as b order by toLower(item.a) asc, item.b desc"
|
|
1317
|
-
);
|
|
1318
|
-
expect(ast).toBeDefined();
|
|
1319
|
-
});
|
|
1320
|
-
|
|
1321
|
-
test("ORDER BY with expression and LIMIT parses correctly", () => {
|
|
1322
|
-
const parser = new Parser();
|
|
1323
|
-
const ast = parser.parse(
|
|
1324
|
-
"unwind ['c', 'a', 'b'] as x return x order by toLower(x) asc limit 2"
|
|
1325
|
-
);
|
|
1326
|
-
expect(ast).toBeDefined();
|
|
1327
|
-
});
|