flowquery 1.0.15 → 1.0.17

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.
Files changed (333) hide show
  1. package/.github/workflows/python-publish.yml +97 -0
  2. package/dist/compute/runner.d.ts +3 -2
  3. package/dist/compute/runner.d.ts.map +1 -1
  4. package/dist/compute/runner.js +7 -7
  5. package/dist/compute/runner.js.map +1 -1
  6. package/dist/flowquery.min.js +1 -1
  7. package/dist/graph/data.d.ts +31 -0
  8. package/dist/graph/data.d.ts.map +1 -0
  9. package/dist/graph/data.js +110 -0
  10. package/dist/graph/data.js.map +1 -0
  11. package/dist/graph/database.d.ts +20 -0
  12. package/dist/graph/database.d.ts.map +1 -0
  13. package/dist/graph/database.js +77 -0
  14. package/dist/graph/database.js.map +1 -0
  15. package/dist/graph/hops.d.ts +11 -0
  16. package/dist/graph/hops.d.ts.map +1 -0
  17. package/dist/graph/hops.js +25 -0
  18. package/dist/graph/hops.js.map +1 -0
  19. package/dist/graph/node.d.ts +35 -0
  20. package/dist/graph/node.d.ts.map +1 -0
  21. package/dist/graph/node.js +113 -0
  22. package/dist/graph/node.js.map +1 -0
  23. package/dist/graph/node_data.d.ts +11 -0
  24. package/dist/graph/node_data.d.ts.map +1 -0
  25. package/dist/graph/node_data.js +20 -0
  26. package/dist/graph/node_data.js.map +1 -0
  27. package/dist/graph/node_reference.d.ts +10 -0
  28. package/dist/graph/node_reference.d.ts.map +1 -0
  29. package/dist/graph/node_reference.js +52 -0
  30. package/dist/graph/node_reference.js.map +1 -0
  31. package/dist/graph/pattern.d.ts +18 -0
  32. package/dist/graph/pattern.d.ts.map +1 -0
  33. package/dist/graph/pattern.js +114 -0
  34. package/dist/graph/pattern.js.map +1 -0
  35. package/dist/graph/pattern_expression.d.ts +14 -0
  36. package/dist/graph/pattern_expression.d.ts.map +1 -0
  37. package/dist/graph/pattern_expression.js +58 -0
  38. package/dist/graph/pattern_expression.js.map +1 -0
  39. package/dist/graph/patterns.d.ts +11 -0
  40. package/dist/graph/patterns.d.ts.map +1 -0
  41. package/dist/graph/patterns.js +49 -0
  42. package/dist/graph/patterns.js.map +1 -0
  43. package/dist/graph/physical_node.d.ts +10 -0
  44. package/dist/graph/physical_node.d.ts.map +1 -0
  45. package/dist/graph/physical_node.js +40 -0
  46. package/dist/graph/physical_node.js.map +1 -0
  47. package/dist/graph/physical_relationship.d.ts +10 -0
  48. package/dist/graph/physical_relationship.d.ts.map +1 -0
  49. package/dist/graph/physical_relationship.js +40 -0
  50. package/dist/graph/physical_relationship.js.map +1 -0
  51. package/dist/graph/relationship.d.ts +40 -0
  52. package/dist/graph/relationship.d.ts.map +1 -0
  53. package/dist/graph/relationship.js +124 -0
  54. package/dist/graph/relationship.js.map +1 -0
  55. package/dist/graph/relationship_data.d.ts +12 -0
  56. package/dist/graph/relationship_data.d.ts.map +1 -0
  57. package/dist/graph/relationship_data.js +40 -0
  58. package/dist/graph/relationship_data.js.map +1 -0
  59. package/dist/graph/relationship_match_collector.d.ts +19 -0
  60. package/dist/graph/relationship_match_collector.d.ts.map +1 -0
  61. package/dist/graph/relationship_match_collector.js +55 -0
  62. package/dist/graph/relationship_match_collector.js.map +1 -0
  63. package/dist/graph/relationship_reference.d.ts +8 -0
  64. package/dist/graph/relationship_reference.d.ts.map +1 -0
  65. package/dist/graph/relationship_reference.js +37 -0
  66. package/dist/graph/relationship_reference.js.map +1 -0
  67. package/dist/parsing/base_parser.d.ts +1 -0
  68. package/dist/parsing/base_parser.d.ts.map +1 -1
  69. package/dist/parsing/base_parser.js +4 -1
  70. package/dist/parsing/base_parser.js.map +1 -1
  71. package/dist/parsing/context.d.ts +2 -2
  72. package/dist/parsing/context.js +5 -5
  73. package/dist/parsing/expressions/boolean.d.ts +8 -0
  74. package/dist/parsing/expressions/boolean.d.ts.map +1 -0
  75. package/dist/parsing/expressions/boolean.js +26 -0
  76. package/dist/parsing/expressions/boolean.js.map +1 -0
  77. package/dist/parsing/expressions/expression.d.ts +4 -1
  78. package/dist/parsing/expressions/expression.d.ts.map +1 -1
  79. package/dist/parsing/expressions/expression.js +15 -8
  80. package/dist/parsing/expressions/expression.js.map +1 -1
  81. package/dist/parsing/expressions/expression_map.d.ts +1 -0
  82. package/dist/parsing/expressions/expression_map.d.ts.map +1 -1
  83. package/dist/parsing/expressions/expression_map.js +3 -0
  84. package/dist/parsing/expressions/expression_map.js.map +1 -1
  85. package/dist/parsing/expressions/operator.d.ts +1 -1
  86. package/dist/parsing/expressions/operator.d.ts.map +1 -1
  87. package/dist/parsing/expressions/operator.js.map +1 -1
  88. package/dist/parsing/functions/function_factory.d.ts +13 -13
  89. package/dist/parsing/functions/function_factory.d.ts.map +1 -1
  90. package/dist/parsing/functions/function_factory.js +20 -18
  91. package/dist/parsing/functions/function_factory.js.map +1 -1
  92. package/dist/parsing/operations/call.d.ts.map +1 -1
  93. package/dist/parsing/operations/call.js +3 -1
  94. package/dist/parsing/operations/call.js.map +1 -1
  95. package/dist/parsing/operations/create_node.d.ts +14 -0
  96. package/dist/parsing/operations/create_node.d.ts.map +1 -0
  97. package/dist/parsing/operations/create_node.js +51 -0
  98. package/dist/parsing/operations/create_node.js.map +1 -0
  99. package/dist/parsing/operations/create_relationship.d.ts +14 -0
  100. package/dist/parsing/operations/create_relationship.d.ts.map +1 -0
  101. package/dist/parsing/operations/create_relationship.js +51 -0
  102. package/dist/parsing/operations/create_relationship.js.map +1 -0
  103. package/dist/parsing/operations/match.d.ts +15 -0
  104. package/dist/parsing/operations/match.d.ts.map +1 -0
  105. package/dist/parsing/operations/match.js +45 -0
  106. package/dist/parsing/operations/match.js.map +1 -0
  107. package/dist/parsing/operations/operation.d.ts +1 -0
  108. package/dist/parsing/operations/operation.d.ts.map +1 -1
  109. package/dist/parsing/operations/operation.js +6 -0
  110. package/dist/parsing/operations/operation.js.map +1 -1
  111. package/dist/parsing/operations/return.d.ts +1 -0
  112. package/dist/parsing/operations/return.d.ts.map +1 -1
  113. package/dist/parsing/operations/return.js +7 -1
  114. package/dist/parsing/operations/return.js.map +1 -1
  115. package/dist/parsing/operations/where.d.ts +1 -1
  116. package/dist/parsing/operations/where.d.ts.map +1 -1
  117. package/dist/parsing/operations/where.js +4 -0
  118. package/dist/parsing/operations/where.js.map +1 -1
  119. package/dist/parsing/parser.d.ts +10 -0
  120. package/dist/parsing/parser.d.ts.map +1 -1
  121. package/dist/parsing/parser.js +344 -5
  122. package/dist/parsing/parser.js.map +1 -1
  123. package/dist/parsing/token_to_node.d.ts.map +1 -1
  124. package/dist/parsing/token_to_node.js +7 -0
  125. package/dist/parsing/token_to_node.js.map +1 -1
  126. package/dist/tokenization/keyword.d.ts +1 -0
  127. package/dist/tokenization/keyword.d.ts.map +1 -1
  128. package/dist/tokenization/keyword.js +1 -0
  129. package/dist/tokenization/keyword.js.map +1 -1
  130. package/dist/tokenization/token.d.ts +4 -0
  131. package/dist/tokenization/token.d.ts.map +1 -1
  132. package/dist/tokenization/token.js +14 -1
  133. package/dist/tokenization/token.js.map +1 -1
  134. package/dist/tokenization/token_type.d.ts +1 -0
  135. package/dist/tokenization/token_type.d.ts.map +1 -1
  136. package/dist/tokenization/token_type.js +1 -0
  137. package/dist/tokenization/token_type.js.map +1 -1
  138. package/dist/tokenization/tokenizer.d.ts +2 -1
  139. package/dist/tokenization/tokenizer.d.ts.map +1 -1
  140. package/dist/tokenization/tokenizer.js +25 -12
  141. package/dist/tokenization/tokenizer.js.map +1 -1
  142. package/docs/flowquery.min.js +1 -1
  143. package/flowquery-py/README.md +166 -0
  144. package/flowquery-py/pyproject.toml +75 -0
  145. package/flowquery-py/setup_env.ps1 +92 -0
  146. package/flowquery-py/setup_env.sh +87 -0
  147. package/flowquery-py/src/__init__.py +34 -0
  148. package/flowquery-py/src/__main__.py +10 -0
  149. package/flowquery-py/src/compute/__init__.py +5 -0
  150. package/flowquery-py/src/compute/runner.py +60 -0
  151. package/flowquery-py/src/extensibility.py +52 -0
  152. package/flowquery-py/src/graph/__init__.py +31 -0
  153. package/flowquery-py/src/graph/data.py +118 -0
  154. package/flowquery-py/src/graph/database.py +82 -0
  155. package/flowquery-py/src/graph/hops.py +43 -0
  156. package/flowquery-py/src/graph/node.py +112 -0
  157. package/flowquery-py/src/graph/node_data.py +26 -0
  158. package/flowquery-py/src/graph/node_reference.py +49 -0
  159. package/flowquery-py/src/graph/pattern.py +125 -0
  160. package/flowquery-py/src/graph/pattern_expression.py +62 -0
  161. package/flowquery-py/src/graph/patterns.py +42 -0
  162. package/flowquery-py/src/graph/physical_node.py +40 -0
  163. package/flowquery-py/src/graph/physical_relationship.py +36 -0
  164. package/flowquery-py/src/graph/relationship.py +135 -0
  165. package/flowquery-py/src/graph/relationship_data.py +33 -0
  166. package/flowquery-py/src/graph/relationship_match_collector.py +77 -0
  167. package/flowquery-py/src/graph/relationship_reference.py +21 -0
  168. package/flowquery-py/src/io/__init__.py +5 -0
  169. package/flowquery-py/src/io/command_line.py +67 -0
  170. package/flowquery-py/src/parsing/__init__.py +17 -0
  171. package/flowquery-py/src/parsing/alias.py +20 -0
  172. package/flowquery-py/src/parsing/alias_option.py +11 -0
  173. package/flowquery-py/src/parsing/ast_node.py +146 -0
  174. package/flowquery-py/src/parsing/base_parser.py +84 -0
  175. package/flowquery-py/src/parsing/components/__init__.py +19 -0
  176. package/flowquery-py/src/parsing/components/csv.py +8 -0
  177. package/flowquery-py/src/parsing/components/from_.py +10 -0
  178. package/flowquery-py/src/parsing/components/headers.py +12 -0
  179. package/flowquery-py/src/parsing/components/json.py +8 -0
  180. package/flowquery-py/src/parsing/components/null.py +10 -0
  181. package/flowquery-py/src/parsing/components/post.py +8 -0
  182. package/flowquery-py/src/parsing/components/text.py +8 -0
  183. package/flowquery-py/src/parsing/context.py +50 -0
  184. package/flowquery-py/src/parsing/data_structures/__init__.py +15 -0
  185. package/flowquery-py/src/parsing/data_structures/associative_array.py +41 -0
  186. package/flowquery-py/src/parsing/data_structures/json_array.py +30 -0
  187. package/flowquery-py/src/parsing/data_structures/key_value_pair.py +38 -0
  188. package/flowquery-py/src/parsing/data_structures/lookup.py +49 -0
  189. package/flowquery-py/src/parsing/data_structures/range_lookup.py +42 -0
  190. package/flowquery-py/src/parsing/expressions/__init__.py +57 -0
  191. package/flowquery-py/src/parsing/expressions/boolean.py +20 -0
  192. package/flowquery-py/src/parsing/expressions/expression.py +138 -0
  193. package/flowquery-py/src/parsing/expressions/expression_map.py +26 -0
  194. package/flowquery-py/src/parsing/expressions/f_string.py +27 -0
  195. package/flowquery-py/src/parsing/expressions/identifier.py +20 -0
  196. package/flowquery-py/src/parsing/expressions/number.py +32 -0
  197. package/flowquery-py/src/parsing/expressions/operator.py +169 -0
  198. package/flowquery-py/src/parsing/expressions/reference.py +47 -0
  199. package/flowquery-py/src/parsing/expressions/string.py +27 -0
  200. package/flowquery-py/src/parsing/functions/__init__.py +75 -0
  201. package/flowquery-py/src/parsing/functions/aggregate_function.py +60 -0
  202. package/flowquery-py/src/parsing/functions/async_function.py +62 -0
  203. package/flowquery-py/src/parsing/functions/avg.py +55 -0
  204. package/flowquery-py/src/parsing/functions/collect.py +75 -0
  205. package/flowquery-py/src/parsing/functions/function.py +68 -0
  206. package/flowquery-py/src/parsing/functions/function_factory.py +173 -0
  207. package/flowquery-py/src/parsing/functions/function_metadata.py +149 -0
  208. package/flowquery-py/src/parsing/functions/functions.py +59 -0
  209. package/flowquery-py/src/parsing/functions/join.py +47 -0
  210. package/flowquery-py/src/parsing/functions/keys.py +34 -0
  211. package/flowquery-py/src/parsing/functions/predicate_function.py +46 -0
  212. package/flowquery-py/src/parsing/functions/predicate_sum.py +47 -0
  213. package/flowquery-py/src/parsing/functions/rand.py +28 -0
  214. package/flowquery-py/src/parsing/functions/range_.py +34 -0
  215. package/flowquery-py/src/parsing/functions/reducer_element.py +15 -0
  216. package/flowquery-py/src/parsing/functions/replace.py +37 -0
  217. package/flowquery-py/src/parsing/functions/round_.py +32 -0
  218. package/flowquery-py/src/parsing/functions/size.py +32 -0
  219. package/flowquery-py/src/parsing/functions/split.py +47 -0
  220. package/flowquery-py/src/parsing/functions/stringify.py +47 -0
  221. package/flowquery-py/src/parsing/functions/sum.py +51 -0
  222. package/flowquery-py/src/parsing/functions/to_json.py +33 -0
  223. package/flowquery-py/src/parsing/functions/type_.py +47 -0
  224. package/flowquery-py/src/parsing/functions/value_holder.py +24 -0
  225. package/flowquery-py/src/parsing/logic/__init__.py +15 -0
  226. package/flowquery-py/src/parsing/logic/case.py +29 -0
  227. package/flowquery-py/src/parsing/logic/else_.py +12 -0
  228. package/flowquery-py/src/parsing/logic/end.py +8 -0
  229. package/flowquery-py/src/parsing/logic/then.py +12 -0
  230. package/flowquery-py/src/parsing/logic/when.py +10 -0
  231. package/flowquery-py/src/parsing/operations/__init__.py +35 -0
  232. package/flowquery-py/src/parsing/operations/aggregated_return.py +24 -0
  233. package/flowquery-py/src/parsing/operations/aggregated_with.py +22 -0
  234. package/flowquery-py/src/parsing/operations/call.py +74 -0
  235. package/flowquery-py/src/parsing/operations/create_node.py +34 -0
  236. package/flowquery-py/src/parsing/operations/create_relationship.py +34 -0
  237. package/flowquery-py/src/parsing/operations/group_by.py +130 -0
  238. package/flowquery-py/src/parsing/operations/limit.py +22 -0
  239. package/flowquery-py/src/parsing/operations/load.py +140 -0
  240. package/flowquery-py/src/parsing/operations/match.py +29 -0
  241. package/flowquery-py/src/parsing/operations/operation.py +69 -0
  242. package/flowquery-py/src/parsing/operations/projection.py +21 -0
  243. package/flowquery-py/src/parsing/operations/return_op.py +50 -0
  244. package/flowquery-py/src/parsing/operations/unwind.py +37 -0
  245. package/flowquery-py/src/parsing/operations/where.py +41 -0
  246. package/flowquery-py/src/parsing/operations/with_op.py +18 -0
  247. package/flowquery-py/src/parsing/parser.py +1011 -0
  248. package/flowquery-py/src/parsing/token_to_node.py +109 -0
  249. package/flowquery-py/src/tokenization/__init__.py +23 -0
  250. package/flowquery-py/src/tokenization/keyword.py +48 -0
  251. package/flowquery-py/src/tokenization/operator.py +29 -0
  252. package/flowquery-py/src/tokenization/string_walker.py +158 -0
  253. package/flowquery-py/src/tokenization/symbol.py +19 -0
  254. package/flowquery-py/src/tokenization/token.py +659 -0
  255. package/flowquery-py/src/tokenization/token_mapper.py +52 -0
  256. package/flowquery-py/src/tokenization/token_type.py +21 -0
  257. package/flowquery-py/src/tokenization/tokenizer.py +214 -0
  258. package/flowquery-py/src/tokenization/trie.py +124 -0
  259. package/flowquery-py/src/utils/__init__.py +6 -0
  260. package/flowquery-py/src/utils/object_utils.py +20 -0
  261. package/flowquery-py/src/utils/string_utils.py +113 -0
  262. package/flowquery-py/tests/__init__.py +1 -0
  263. package/flowquery-py/tests/compute/__init__.py +1 -0
  264. package/flowquery-py/tests/compute/test_runner.py +1335 -0
  265. package/flowquery-py/tests/graph/__init__.py +1 -0
  266. package/flowquery-py/tests/graph/test_create.py +56 -0
  267. package/flowquery-py/tests/graph/test_data.py +73 -0
  268. package/flowquery-py/tests/graph/test_match.py +40 -0
  269. package/flowquery-py/tests/parsing/__init__.py +1 -0
  270. package/flowquery-py/tests/parsing/test_context.py +34 -0
  271. package/flowquery-py/tests/parsing/test_expression.py +49 -0
  272. package/flowquery-py/tests/parsing/test_parser.py +674 -0
  273. package/flowquery-py/tests/test_extensibility.py +611 -0
  274. package/flowquery-py/tests/tokenization/__init__.py +1 -0
  275. package/flowquery-py/tests/tokenization/test_token_mapper.py +60 -0
  276. package/flowquery-py/tests/tokenization/test_tokenizer.py +164 -0
  277. package/flowquery-py/tests/tokenization/test_trie.py +30 -0
  278. package/flowquery-vscode/flowQueryEngine/flowquery.min.js +1 -1
  279. package/misc/apps/RAG/package.json +1 -1
  280. package/misc/apps/RAG/src/components/AdaptiveCardRenderer.tsx +76 -8
  281. package/misc/apps/RAG/src/components/index.ts +19 -10
  282. package/misc/apps/RAG/src/plugins/loaders/CatFacts.ts +21 -26
  283. package/misc/apps/RAG/src/plugins/loaders/FetchJson.ts +24 -25
  284. package/misc/apps/RAG/src/plugins/loaders/Form.ts +163 -147
  285. package/misc/apps/RAG/src/plugins/loaders/Llm.ts +103 -90
  286. package/misc/apps/RAG/src/plugins/loaders/MockData.ts +80 -130
  287. package/misc/apps/RAG/src/plugins/loaders/Table.ts +104 -101
  288. package/misc/apps/RAG/src/plugins/loaders/Weather.ts +47 -36
  289. package/misc/apps/RAG/src/prompts/FlowQuerySystemPrompt.ts +89 -78
  290. package/package.json +1 -1
  291. package/src/compute/runner.ts +24 -19
  292. package/src/graph/data.ts +112 -0
  293. package/src/graph/database.ts +63 -0
  294. package/src/graph/hops.ts +22 -0
  295. package/src/graph/node.ts +99 -0
  296. package/src/graph/node_data.ts +18 -0
  297. package/src/graph/node_reference.ts +33 -0
  298. package/src/graph/pattern.ts +101 -0
  299. package/src/graph/pattern_expression.ts +37 -0
  300. package/src/graph/patterns.ts +36 -0
  301. package/src/graph/physical_node.ts +23 -0
  302. package/src/graph/physical_relationship.ts +23 -0
  303. package/src/graph/relationship.ts +116 -0
  304. package/src/graph/relationship_data.ts +27 -0
  305. package/src/graph/relationship_match_collector.ts +58 -0
  306. package/src/graph/relationship_reference.ts +24 -0
  307. package/src/parsing/base_parser.ts +20 -14
  308. package/src/parsing/context.ts +14 -14
  309. package/src/parsing/expressions/boolean.ts +21 -0
  310. package/src/parsing/expressions/expression.ts +34 -26
  311. package/src/parsing/expressions/expression_map.ts +3 -0
  312. package/src/parsing/expressions/operator.ts +19 -1
  313. package/src/parsing/functions/function_factory.ts +45 -45
  314. package/src/parsing/operations/call.ts +3 -1
  315. package/src/parsing/operations/create_node.ts +39 -0
  316. package/src/parsing/operations/create_relationship.ts +38 -0
  317. package/src/parsing/operations/match.ts +31 -0
  318. package/src/parsing/operations/operation.ts +3 -0
  319. package/src/parsing/operations/return.ts +11 -7
  320. package/src/parsing/operations/where.ts +10 -6
  321. package/src/parsing/parser.ts +346 -8
  322. package/src/parsing/token_to_node.ts +6 -0
  323. package/src/tokenization/keyword.ts +41 -40
  324. package/src/tokenization/token.ts +21 -1
  325. package/src/tokenization/token_type.ts +2 -1
  326. package/src/tokenization/tokenizer.ts +52 -31
  327. package/tests/compute/runner.test.ts +660 -6
  328. package/tests/extensibility.test.ts +97 -93
  329. package/tests/graph/create.test.ts +36 -0
  330. package/tests/graph/data.test.ts +58 -0
  331. package/tests/graph/match.test.ts +29 -0
  332. package/tests/parsing/parser.test.ts +276 -8
  333. package/tests/tokenization/tokenizer.test.ts +107 -17
@@ -1,4 +1,6 @@
1
1
  import Runner from "../../src/compute/runner";
2
+ import Database from "../../src/graph/database";
3
+ import Node from "../../src/graph/node";
2
4
  import AsyncFunction from "../../src/parsing/functions/async_function";
3
5
  import { FunctionDef } from "../../src/parsing/functions/function_metadata";
4
6
 
@@ -15,9 +17,9 @@ class CallTestFunction extends AsyncFunction {
15
17
  this._expectedParameterCount = 0;
16
18
  }
17
19
  public async *generate(): AsyncGenerator<any> {
18
- yield { result: 1 };
19
- yield { result: 2 };
20
- yield { result: 3 };
20
+ yield { result: 1, dummy: "a" };
21
+ yield { result: 2, dummy: "b" };
22
+ yield { result: 3, dummy: "c" };
21
23
  }
22
24
  }
23
25
 
@@ -616,9 +618,9 @@ test("Test call operation as last operation", async () => {
616
618
  await runner.run();
617
619
  const results = runner.results;
618
620
  expect(results.length).toBe(3);
619
- expect(results[0]).toEqual({ result: 1 });
620
- expect(results[1]).toEqual({ result: 2 });
621
- expect(results[2]).toEqual({ result: 3 });
621
+ expect(results[0]).toEqual({ result: 1, dummy: "a" });
622
+ expect(results[1]).toEqual({ result: 2, dummy: "b" });
623
+ expect(results[2]).toEqual({ result: 3, dummy: "c" });
622
624
  });
623
625
 
624
626
  test("Test call operation as last operation with yield", async () => {
@@ -636,3 +638,655 @@ test("Test call operation with no yielded expressions", async () => {
636
638
  const runner = new Runner("CALL calltestfunctionnoobject() RETURN 1");
637
639
  }).toThrow("CALL operations must have a YIELD clause unless they are the last operation");
638
640
  });
641
+
642
+ test("Test create node operation", async () => {
643
+ const db = Database.getInstance();
644
+ const runner = new Runner(`
645
+ CREATE VIRTUAL (:Person) AS {
646
+ with 1 as x
647
+ RETURN x
648
+ }
649
+ `);
650
+ await runner.run();
651
+ const results = runner.results;
652
+ expect(results.length).toBe(0);
653
+ expect(db.getNode(new Node(null, "Person"))).not.toBeNull();
654
+ });
655
+
656
+ test("Test create node and match operations", async () => {
657
+ const create = new Runner(`
658
+ CREATE VIRTUAL (:Person) AS {
659
+ unwind [
660
+ {id: 1, name: 'Person 1'},
661
+ {id: 2, name: 'Person 2'}
662
+ ] as record
663
+ RETURN record.id as id, record.name as name
664
+ }
665
+ `);
666
+ await create.run();
667
+ const match = new Runner("MATCH (n:Person) RETURN n");
668
+ await match.run();
669
+ const results = match.results;
670
+ expect(results.length).toBe(2);
671
+ expect(results[0].n).toBeDefined();
672
+ expect(results[0].n.id).toBe(1);
673
+ expect(results[0].n.name).toBe("Person 1");
674
+ expect(results[1].n).toBeDefined();
675
+ expect(results[1].n.id).toBe(2);
676
+ expect(results[1].n.name).toBe("Person 2");
677
+ });
678
+
679
+ test("Test complex match operation", async () => {
680
+ await new Runner(`
681
+ CREATE VIRTUAL (:Person) AS {
682
+ unwind [
683
+ {id: 1, name: 'Person 1', age: 30},
684
+ {id: 2, name: 'Person 2', age: 25},
685
+ {id: 3, name: 'Person 3', age: 35}
686
+ ] as record
687
+ RETURN record.id as id, record.name as name, record.age as age
688
+ }
689
+ `).run();
690
+ const match = new Runner(`
691
+ MATCH (n:Person)
692
+ WHERE n.age > 29
693
+ RETURN n.name AS name, n.age AS age
694
+ `);
695
+ await match.run();
696
+ const results = match.results;
697
+ expect(results.length).toBe(2);
698
+ expect(results[0]).toEqual({ name: "Person 1", age: 30 });
699
+ expect(results[1]).toEqual({ name: "Person 3", age: 35 });
700
+ });
701
+
702
+ test("Test match", async () => {
703
+ await new Runner(`
704
+ CREATE VIRTUAL (:Person) AS {
705
+ unwind [
706
+ {id: 1, name: 'Person 1'},
707
+ {id: 2, name: 'Person 2'}
708
+ ] as record
709
+ RETURN record.id as id, record.name as name
710
+ }
711
+ `).run();
712
+ const match = new Runner(`
713
+ MATCH (n:Person)
714
+ RETURN n.name AS name
715
+ `);
716
+ await match.run();
717
+ const results = match.results;
718
+ expect(results.length).toBe(2);
719
+ expect(results[0]).toEqual({ name: "Person 1" });
720
+ expect(results[1]).toEqual({ name: "Person 2" });
721
+ });
722
+
723
+ test("Test match with nested join", async () => {
724
+ await new Runner(`
725
+ CREATE VIRTUAL (:Person) AS {
726
+ unwind [
727
+ {id: 1, name: 'Person 1'},
728
+ {id: 2, name: 'Person 2'}
729
+ ] as record
730
+ RETURN record.id as id, record.name as name
731
+ }
732
+ `).run();
733
+ const match = new Runner(`
734
+ MATCH (a:Person), (b:Person)
735
+ WHERE a.id <> b.id
736
+ RETURN a.name AS name1, b.name AS name2
737
+ `);
738
+ await match.run();
739
+ const results = match.results;
740
+ expect(results.length).toBe(2);
741
+ expect(results[0]).toEqual({ name1: "Person 1", name2: "Person 2" });
742
+ expect(results[1]).toEqual({ name1: "Person 2", name2: "Person 1" });
743
+ });
744
+
745
+ test("Test match with graph pattern", async () => {
746
+ await new Runner(`
747
+ CREATE VIRTUAL (:User) AS {
748
+ UNWIND [
749
+ {id: 1, name: 'User 1', manager_id: null},
750
+ {id: 2, name: 'User 2', manager_id: 1},
751
+ {id: 3, name: 'User 3', manager_id: 1},
752
+ {id: 4, name: 'User 4', manager_id: 2}
753
+ ] AS record
754
+ RETURN record.id AS id, record.name AS name, record.manager_id AS manager_id
755
+ }
756
+ `).run();
757
+ await new Runner(`
758
+ CREATE VIRTUAL (:User)-[:MANAGED_BY]-(:User) AS {
759
+ UNWIND [
760
+ {id: 1, manager_id: null},
761
+ {id: 2, manager_id: 1},
762
+ {id: 3, manager_id: 1},
763
+ {id: 4, manager_id: 2}
764
+ ] AS record
765
+ RETURN record.id AS left_id, record.manager_id AS right_id
766
+ }
767
+ `).run();
768
+ const match = new Runner(`
769
+ MATCH (user:User)-[r:MANAGED_BY]-(manager:User)
770
+ RETURN user.name AS user, manager.name AS manager
771
+ `);
772
+ await match.run();
773
+ const results = match.results;
774
+ expect(results.length).toBe(3);
775
+ expect(results[0]).toEqual({ user: "User 2", manager: "User 1" });
776
+ expect(results[1]).toEqual({ user: "User 3", manager: "User 1" });
777
+ expect(results[2]).toEqual({ user: "User 4", manager: "User 2" });
778
+ });
779
+
780
+ test("Test match with multiple hop graph pattern", async () => {
781
+ await new Runner(`
782
+ CREATE VIRTUAL (:Person) AS {
783
+ unwind [
784
+ {id: 1, name: 'Person 1'},
785
+ {id: 2, name: 'Person 2'},
786
+ {id: 3, name: 'Person 3'},
787
+ {id: 4, name: 'Person 4'}
788
+ ] as record
789
+ RETURN record.id as id, record.name as name
790
+ }
791
+ `).run();
792
+ await new Runner(`
793
+ CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
794
+ unwind [
795
+ {left_id: 1, right_id: 2},
796
+ {left_id: 2, right_id: 3}
797
+ ] as record
798
+ RETURN record.left_id as left_id, record.right_id as right_id
799
+ }
800
+ `).run();
801
+ const match = new Runner(`
802
+ MATCH (a:Person)-[:KNOWS*]-(c:Person)
803
+ RETURN a.name AS name1, c.name AS name2
804
+ `);
805
+ await match.run();
806
+ const results = match.results;
807
+ expect(results.length).toBe(3);
808
+ expect(results[0]).toEqual({ name1: "Person 1", name2: "Person 2" });
809
+ expect(results[1]).toEqual({ name1: "Person 1", name2: "Person 3" });
810
+ expect(results[2]).toEqual({ name1: "Person 2", name2: "Person 3" });
811
+ });
812
+
813
+ test("Test match with double graph pattern", async () => {
814
+ await new Runner(`
815
+ CREATE VIRTUAL (:Person) AS {
816
+ unwind [
817
+ {id: 1, name: 'Person 1'},
818
+ {id: 2, name: 'Person 2'},
819
+ {id: 3, name: 'Person 3'},
820
+ {id: 4, name: 'Person 4'}
821
+ ] as record
822
+ RETURN record.id as id, record.name as name
823
+ }
824
+ `).run();
825
+ await new Runner(`
826
+ CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
827
+ unwind [
828
+ {left_id: 1, right_id: 2},
829
+ {left_id: 2, right_id: 3},
830
+ {left_id: 3, right_id: 4}
831
+ ] as record
832
+ RETURN record.left_id as left_id, record.right_id as right_id
833
+ }
834
+ `).run();
835
+ const match = new Runner(`
836
+ MATCH (a:Person)-[:KNOWS]-(b:Person)-[:KNOWS]-(c:Person)
837
+ RETURN a.name AS name1, b.name AS name2, c.name AS name3
838
+ `);
839
+ await match.run();
840
+ const results = match.results;
841
+ expect(results.length).toBe(2);
842
+ expect(results[0]).toEqual({ name1: "Person 1", name2: "Person 2", name3: "Person 3" });
843
+ expect(results[1]).toEqual({ name1: "Person 2", name2: "Person 3", name3: "Person 4" });
844
+ });
845
+
846
+ test("Test match with referenced to previous variable", async () => {
847
+ await new Runner(`
848
+ CREATE VIRTUAL (:Person) AS {
849
+ unwind [
850
+ {id: 1, name: 'Person 1'},
851
+ {id: 2, name: 'Person 2'},
852
+ {id: 3, name: 'Person 3'},
853
+ {id: 4, name: 'Person 4'}
854
+ ] as record
855
+ RETURN record.id as id, record.name as name
856
+ }
857
+ `).run();
858
+ await new Runner(`
859
+ CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
860
+ unwind [
861
+ {left_id: 1, right_id: 2},
862
+ {left_id: 2, right_id: 3},
863
+ {left_id: 3, right_id: 4}
864
+ ] as record
865
+ RETURN record.left_id as left_id, record.right_id as right_id
866
+ }
867
+ `).run();
868
+ const match = new Runner(`
869
+ MATCH (a:Person)-[:KNOWS]-(b:Person)
870
+ MATCH (b)-[:KNOWS]-(c:Person)
871
+ RETURN a.name AS name1, b.name AS name2, c.name AS name3
872
+ `);
873
+ await match.run();
874
+ const results = match.results;
875
+ expect(results.length).toBe(2);
876
+ expect(results[0]).toEqual({ name1: "Person 1", name2: "Person 2", name3: "Person 3" });
877
+ expect(results[1]).toEqual({ name1: "Person 2", name2: "Person 3", name3: "Person 4" });
878
+ });
879
+
880
+ test("Test match and return full node", async () => {
881
+ await new Runner(`
882
+ CREATE VIRTUAL (:Person) AS {
883
+ unwind [
884
+ {id: 1, name: 'Person 1'},
885
+ {id: 2, name: 'Person 2'}
886
+ ] as record
887
+ RETURN record.id as id, record.name as name
888
+ }
889
+ `).run();
890
+ const match = new Runner(`
891
+ MATCH (n:Person)
892
+ RETURN n
893
+ `);
894
+ await match.run();
895
+ const results = match.results;
896
+ expect(results.length).toBe(2);
897
+ expect(results[0].n).toBeDefined();
898
+ expect(results[0].n.id).toBe(1);
899
+ expect(results[0].n.name).toBe("Person 1");
900
+ expect(results[1].n).toBeDefined();
901
+ expect(results[1].n.id).toBe(2);
902
+ expect(results[1].n.name).toBe("Person 2");
903
+ });
904
+
905
+ test("Test return graph pattern", async () => {
906
+ await new Runner(`
907
+ CREATE VIRTUAL (:Person) AS {
908
+ unwind [
909
+ {id: 1, name: 'Person 1'},
910
+ {id: 2, name: 'Person 2'}
911
+ ] as record
912
+ RETURN record.id as id, record.name as name
913
+ }
914
+ `).run();
915
+ await new Runner(`
916
+ CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
917
+ unwind [
918
+ {left_id: 1, since: "2020-01-01", right_id: 2}
919
+ ] as record
920
+ RETURN record.left_id as left_id, record.since as since, record.right_id as right_id
921
+ }
922
+ `).run();
923
+ const match = new Runner(`
924
+ MATCH p=(:Person)-[:KNOWS]-(:Person)
925
+ RETURN p AS pattern
926
+ `);
927
+ await match.run();
928
+ const results = match.results;
929
+ expect(results.length).toBe(1);
930
+ expect(results[0].pattern).toBeDefined();
931
+ expect(results[0].pattern.length).toBe(3);
932
+ expect(results[0].pattern[0].id).toBe(1);
933
+ expect(results[0].pattern[1].properties.since).toBe("2020-01-01");
934
+ expect(results[0].pattern[2].id).toBe(2);
935
+ });
936
+
937
+ test("Test circular graph pattern", async () => {
938
+ await new Runner(`
939
+ CREATE VIRTUAL (:Person) AS {
940
+ unwind [
941
+ {id: 1, name: 'Person 1'},
942
+ {id: 2, name: 'Person 2'}
943
+ ] as record
944
+ RETURN record.id as id, record.name as name
945
+ }
946
+ `).run();
947
+ await new Runner(`
948
+ CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
949
+ unwind [
950
+ {left_id: 1, right_id: 2},
951
+ {left_id: 2, right_id: 1}
952
+ ] as record
953
+ RETURN record.left_id as left_id, record.right_id as right_id
954
+ }
955
+ `).run();
956
+ const match = new Runner(`
957
+ MATCH p=(:Person)-[:KNOWS]-(:Person)-[:KNOWS]-(:Person)
958
+ RETURN p AS pattern
959
+ `);
960
+ await match.run();
961
+ const results = match.results;
962
+ expect(results.length).toBe(2);
963
+ expect(results[0].pattern).toBeDefined();
964
+ expect(results[0].pattern.length).toBe(5);
965
+ expect(results[0].pattern[0].id).toBe(1);
966
+ expect(results[0].pattern[1].id).toBeUndefined();
967
+ expect(results[0].pattern[2].id).toBe(2);
968
+ expect(results[0].pattern[3].id).toBeUndefined();
969
+ expect(results[0].pattern[4].id).toBe(1);
970
+ });
971
+
972
+ test("Test circular graph pattern with variable length should throw error", async () => {
973
+ await new Runner(`
974
+ CREATE VIRTUAL (:Person) AS {
975
+ unwind [
976
+ {id: 1, name: 'Person 1'},
977
+ {id: 2, name: 'Person 2'}
978
+ ] as record
979
+ RETURN record.id as id, record.name as name
980
+ }
981
+ `).run();
982
+ await new Runner(`
983
+ CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
984
+ unwind [
985
+ {left_id: 1, right_id: 2},
986
+ {left_id: 2, right_id: 1}
987
+ ] as record
988
+ RETURN record.left_id as left_id, record.right_id as right_id
989
+ }
990
+ `).run();
991
+ const match = new Runner(`
992
+ MATCH p=(:Person)-[:KNOWS*]-(:Person)
993
+ RETURN p AS pattern
994
+ `);
995
+ await expect(async () => {
996
+ await match.run();
997
+ }).rejects.toThrow("Circular relationship detected");
998
+ });
999
+
1000
+ test("Test multi-hop match with variable length relationships", async () => {
1001
+ await new Runner(`
1002
+ CREATE VIRTUAL (:Person) AS {
1003
+ unwind [
1004
+ {id: 1, name: 'Person 1'},
1005
+ {id: 2, name: 'Person 2'},
1006
+ {id: 3, name: 'Person 3'},
1007
+ {id: 4, name: 'Person 4'}
1008
+ ] as record
1009
+ RETURN record.id as id, record.name as name
1010
+ }
1011
+ `).run();
1012
+ await new Runner(`
1013
+ CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
1014
+ unwind [
1015
+ {left_id: 1, right_id: 2},
1016
+ {left_id: 2, right_id: 3},
1017
+ {left_id: 3, right_id: 4}
1018
+ ] as record
1019
+ RETURN record.left_id as left_id, record.right_id as right_id
1020
+ }
1021
+ `).run();
1022
+ const match = new Runner(`
1023
+ MATCH (a:Person)-[r:KNOWS*0..3]->(b:Person)
1024
+ RETURN a, r, b
1025
+ `);
1026
+ await match.run();
1027
+ const results = match.results;
1028
+ expect(results.length).toBe(6);
1029
+
1030
+ expect(results[0].a.id).toBe(1);
1031
+ expect(results[0].b.id).toBe(2);
1032
+ expect(results[0].r.length).toBe(undefined);
1033
+ expect(results[0].r.startNode.id).toBe(1);
1034
+ expect(results[0].r.endNode.id).toBe(2);
1035
+
1036
+ expect(results[1].a.id).toBe(1);
1037
+ expect(results[1].b.id).toBe(3);
1038
+ expect(results[1].r.length).toBe(2);
1039
+ expect(results[1].r[0].startNode.id).toBe(1);
1040
+ expect(results[1].r[0].endNode.id).toBe(2);
1041
+ expect(results[1].r[1].startNode.id).toBe(2);
1042
+ expect(results[1].r[1].endNode.id).toBe(3);
1043
+
1044
+ expect(results[2].a.id).toBe(1);
1045
+ expect(results[2].b.id).toBe(4);
1046
+ expect(results[2].r.length).toBe(3);
1047
+ expect(results[2].r[0].startNode.id).toBe(1);
1048
+ expect(results[2].r[0].endNode.id).toBe(2);
1049
+ expect(results[2].r[1].startNode.id).toBe(2);
1050
+ expect(results[2].r[1].endNode.id).toBe(3);
1051
+ expect(results[2].r[2].startNode.id).toBe(3);
1052
+ expect(results[2].r[2].endNode.id).toBe(4);
1053
+
1054
+ expect(results[3].a.id).toBe(2);
1055
+ expect(results[3].b.id).toBe(3);
1056
+ expect(results[3].r.length).toBe(undefined);
1057
+ expect(results[3].r.startNode.id).toBe(2);
1058
+ expect(results[3].r.endNode.id).toBe(3);
1059
+
1060
+ expect(results[4].a.id).toBe(2);
1061
+ expect(results[4].b.id).toBe(4);
1062
+ expect(results[4].r.length).toBe(2);
1063
+ expect(results[4].r[0].startNode.id).toBe(2);
1064
+ expect(results[4].r[0].endNode.id).toBe(3);
1065
+ expect(results[4].r[1].startNode.id).toBe(3);
1066
+ expect(results[4].r[1].endNode.id).toBe(4);
1067
+
1068
+ expect(results[5].a.id).toBe(3);
1069
+ expect(results[5].b.id).toBe(4);
1070
+ expect(results[5].r.length).toBe(undefined);
1071
+ expect(results[5].r.startNode.id).toBe(3);
1072
+ expect(results[5].r.endNode.id).toBe(4);
1073
+ });
1074
+
1075
+ test("Test return match pattern with variable length relationships", async () => {
1076
+ await new Runner(`
1077
+ CREATE VIRTUAL (:Person) AS {
1078
+ unwind [
1079
+ {id: 1, name: 'Person 1'},
1080
+ {id: 2, name: 'Person 2'},
1081
+ {id: 3, name: 'Person 3'},
1082
+ {id: 4, name: 'Person 4'}
1083
+ ] as record
1084
+ RETURN record.id as id, record.name as name
1085
+ }
1086
+ `).run();
1087
+ await new Runner(`
1088
+ CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
1089
+ unwind [
1090
+ {left_id: 1, right_id: 2},
1091
+ {left_id: 2, right_id: 3},
1092
+ {left_id: 3, right_id: 4}
1093
+ ] as record
1094
+ RETURN record.left_id as left_id, record.right_id as right_id
1095
+ }
1096
+ `).run();
1097
+ const match = new Runner(`
1098
+ MATCH p=(a:Person)-[:KNOWS*0..3]->(b:Person)
1099
+ RETURN p AS pattern
1100
+ `);
1101
+ await match.run();
1102
+ const results = match.results;
1103
+ expect(results.length).toBe(6);
1104
+
1105
+ expect(results[0].pattern.length).toBe(3);
1106
+ expect(results[0].pattern[0].id).toBe(1);
1107
+ expect(results[0].pattern[1].startNode.id).toBe(1);
1108
+ expect(results[0].pattern[1].endNode.id).toBe(2);
1109
+ expect(results[0].pattern[2].id).toBe(2);
1110
+
1111
+ expect(results[1].pattern.length).toBe(5);
1112
+ expect(results[1].pattern[0].id).toBe(1);
1113
+ expect(results[1].pattern[1].startNode.id).toBe(1);
1114
+ expect(results[1].pattern[1].endNode.id).toBe(2);
1115
+ expect(results[1].pattern[2].id).toBe(2);
1116
+ expect(results[1].pattern[3].startNode.id).toBe(2);
1117
+ expect(results[1].pattern[3].endNode.id).toBe(3);
1118
+ expect(results[1].pattern[4].id).toBe(3);
1119
+
1120
+ expect(results[2].pattern.length).toBe(7);
1121
+ expect(results[2].pattern[0].id).toBe(1);
1122
+ expect(results[2].pattern[1].startNode.id).toBe(1);
1123
+ expect(results[2].pattern[1].endNode.id).toBe(2);
1124
+ expect(results[2].pattern[2].id).toBe(2);
1125
+ expect(results[2].pattern[3].startNode.id).toBe(2);
1126
+ expect(results[2].pattern[3].endNode.id).toBe(3);
1127
+ expect(results[2].pattern[4].id).toBe(3);
1128
+ expect(results[2].pattern[5].startNode.id).toBe(3);
1129
+ expect(results[2].pattern[5].endNode.id).toBe(4);
1130
+ expect(results[2].pattern[6].id).toBe(4);
1131
+
1132
+ expect(results[3].pattern.length).toBe(3);
1133
+ expect(results[3].pattern[0].id).toBe(2);
1134
+ expect(results[3].pattern[1].startNode.id).toBe(2);
1135
+ expect(results[3].pattern[1].endNode.id).toBe(3);
1136
+ expect(results[3].pattern[2].id).toBe(3);
1137
+
1138
+ expect(results[4].pattern.length).toBe(5);
1139
+ expect(results[4].pattern[0].id).toBe(2);
1140
+ expect(results[4].pattern[1].startNode.id).toBe(2);
1141
+ expect(results[4].pattern[1].endNode.id).toBe(3);
1142
+ expect(results[4].pattern[2].id).toBe(3);
1143
+ expect(results[4].pattern[3].startNode.id).toBe(3);
1144
+ expect(results[4].pattern[3].endNode.id).toBe(4);
1145
+ expect(results[4].pattern[4].id).toBe(4);
1146
+
1147
+ expect(results[5].pattern.length).toBe(3);
1148
+ expect(results[5].pattern[0].id).toBe(3);
1149
+ expect(results[5].pattern[1].startNode.id).toBe(3);
1150
+ expect(results[5].pattern[1].endNode.id).toBe(4);
1151
+ expect(results[5].pattern[2].id).toBe(4);
1152
+ });
1153
+
1154
+ test("Test statement with graph pattern in where clause", async () => {
1155
+ await new Runner(`
1156
+ CREATE VIRTUAL (:Person) AS {
1157
+ unwind [
1158
+ {id: 1, name: 'Person 1'},
1159
+ {id: 2, name: 'Person 2'},
1160
+ {id: 3, name: 'Person 3'},
1161
+ {id: 4, name: 'Person 4'}
1162
+ ] as record
1163
+ RETURN record.id as id, record.name as name
1164
+ }
1165
+ `).run();
1166
+ await new Runner(`
1167
+ CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
1168
+ unwind [
1169
+ {left_id: 1, right_id: 2},
1170
+ {left_id: 2, right_id: 3},
1171
+ {left_id: 3, right_id: 4}
1172
+ ] as record
1173
+ RETURN record.left_id as left_id, record.right_id as right_id
1174
+ }
1175
+ `).run();
1176
+ // Test positive match
1177
+ const match = new Runner(`
1178
+ MATCH (a:Person), (b:Person)
1179
+ WHERE (a)-[:KNOWS]->(b)
1180
+ RETURN a.name AS name1, b.name AS name2
1181
+ `);
1182
+ await match.run();
1183
+ const results = match.results;
1184
+ expect(results.length).toBe(3);
1185
+ expect(results[0]).toEqual({ name1: "Person 1", name2: "Person 2" });
1186
+ expect(results[1]).toEqual({ name1: "Person 2", name2: "Person 3" });
1187
+ expect(results[2]).toEqual({ name1: "Person 3", name2: "Person 4" });
1188
+
1189
+ // Test negative match
1190
+ const nomatch = new Runner(`
1191
+ MATCH (a:Person), (b:Person)
1192
+ WHERE (a)-[:KNOWS]->(b) <> true
1193
+ RETURN a.name AS name1, b.name AS name2
1194
+ `);
1195
+ await nomatch.run();
1196
+ const noresults = nomatch.results;
1197
+ expect(noresults.length).toBe(13);
1198
+ expect(noresults[0]).toEqual({ name1: "Person 1", name2: "Person 1" });
1199
+ expect(noresults[1]).toEqual({ name1: "Person 1", name2: "Person 3" });
1200
+ expect(noresults[2]).toEqual({ name1: "Person 1", name2: "Person 4" });
1201
+ expect(noresults[3]).toEqual({ name1: "Person 2", name2: "Person 1" });
1202
+ expect(noresults[4]).toEqual({ name1: "Person 2", name2: "Person 2" });
1203
+ expect(noresults[5]).toEqual({ name1: "Person 2", name2: "Person 4" });
1204
+ expect(noresults[6]).toEqual({ name1: "Person 3", name2: "Person 1" });
1205
+ expect(noresults[7]).toEqual({ name1: "Person 3", name2: "Person 2" });
1206
+ expect(noresults[8]).toEqual({ name1: "Person 3", name2: "Person 3" });
1207
+ expect(noresults[9]).toEqual({ name1: "Person 4", name2: "Person 1" });
1208
+ expect(noresults[10]).toEqual({ name1: "Person 4", name2: "Person 2" });
1209
+ expect(noresults[11]).toEqual({ name1: "Person 4", name2: "Person 3" });
1210
+ expect(noresults[12]).toEqual({ name1: "Person 4", name2: "Person 4" });
1211
+ });
1212
+
1213
+ test("Test person who does not know anyone", async () => {
1214
+ await new Runner(`
1215
+ CREATE VIRTUAL (:Person) AS {
1216
+ unwind [
1217
+ {id: 1, name: 'Person 1'},
1218
+ {id: 2, name: 'Person 2'},
1219
+ {id: 3, name: 'Person 3'}
1220
+ ] as record
1221
+ RETURN record.id as id, record.name as name
1222
+ }
1223
+ `).run();
1224
+ await new Runner(`
1225
+ CREATE VIRTUAL (:Person)-[:KNOWS]-(:Person) AS {
1226
+ unwind [
1227
+ {left_id: 1, right_id: 2},
1228
+ {left_id: 2, right_id: 1}
1229
+ ] as record
1230
+ RETURN record.left_id as left_id, record.right_id as right_id
1231
+ }
1232
+ `).run();
1233
+ const match = new Runner(`
1234
+ MATCH (a:Person)
1235
+ WHERE NOT (a)-[:KNOWS]->(:Person)
1236
+ RETURN a.name AS name
1237
+ `);
1238
+ await match.run();
1239
+ const results = match.results;
1240
+ expect(results.length).toBe(1);
1241
+ expect(results[0]).toEqual({ name: "Person 3" });
1242
+ });
1243
+
1244
+ test("Test manager chain", async () => {
1245
+ await new Runner(`
1246
+ CREATE VIRTUAL (:Employee) AS {
1247
+ unwind [
1248
+ {id: 1, name: 'Employee 1'},
1249
+ {id: 2, name: 'Employee 2'},
1250
+ {id: 3, name: 'Employee 3'},
1251
+ {id: 4, name: 'Employee 4'}
1252
+ ] as record
1253
+ RETURN record.id as id, record.name as name
1254
+ }
1255
+ `).run();
1256
+ await new Runner(`
1257
+ CREATE VIRTUAL (:Employee)-[:MANAGED_BY]-(:Employee) AS {
1258
+ unwind [
1259
+ {left_id: 2, right_id: 1},
1260
+ {left_id: 3, right_id: 2},
1261
+ {left_id: 4, right_id: 2}
1262
+ ] as record
1263
+ RETURN record.left_id as left_id, record.right_id as right_id
1264
+ }
1265
+ `).run();
1266
+ const match = new Runner(`
1267
+ MATCH p=(e:Employee)-[:MANAGED_BY*]->(m:Employee)
1268
+ WHERE NOT (m)-[:MANAGED_BY]->(:Employee)
1269
+ RETURN p
1270
+ `);
1271
+ await match.run();
1272
+ const results = match.results;
1273
+ expect(results.length).toBe(2);
1274
+ });
1275
+
1276
+ test("Test equality comparison", async () => {
1277
+ const runner = new Runner(`
1278
+ unwind range(1,10) as i
1279
+ return i=5 as \`isEqual\`, i<>5 as \`isNotEqual\`
1280
+ `);
1281
+ await runner.run();
1282
+ const results = runner.results;
1283
+ expect(results.length).toBe(10);
1284
+ for (let index = 0; index < results.length; index++) {
1285
+ const result = results[index];
1286
+ if (index + 1 === 5) {
1287
+ expect(result).toEqual({ isEqual: 1, isNotEqual: 0 });
1288
+ } else {
1289
+ expect(result).toEqual({ isEqual: 0, isNotEqual: 1 });
1290
+ }
1291
+ }
1292
+ });