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
@@ -57,6 +57,9 @@ abstract class Operation extends ASTNode {
57
57
  public async finish(): Promise<void> {
58
58
  await this.next?.finish();
59
59
  }
60
+ public async initialize(): Promise<void> {
61
+ await this.next?.initialize();
62
+ }
60
63
  public reset(): void {}
61
64
  public get results(): Record<string, any>[] {
62
65
  throw new Error("Not implemented");
@@ -3,10 +3,10 @@ import Where from "./where";
3
3
 
4
4
  /**
5
5
  * Represents a RETURN operation that produces the final query results.
6
- *
6
+ *
7
7
  * The RETURN operation evaluates expressions and collects them into result records.
8
8
  * It can optionally have a WHERE clause to filter results.
9
- *
9
+ *
10
10
  * @example
11
11
  * ```typescript
12
12
  * // RETURN x, y WHERE x > 0
@@ -19,25 +19,29 @@ class Return extends Projection {
19
19
  this._where = where;
20
20
  }
21
21
  public get where(): boolean {
22
- if(this._where === null) {
22
+ if (this._where === null) {
23
23
  return true;
24
24
  }
25
25
  return this._where.value();
26
26
  }
27
27
  public async run(): Promise<void> {
28
- if(!this.where) {
28
+ if (!this.where) {
29
29
  return;
30
30
  }
31
31
  const record: Map<string, any> = new Map();
32
- for(const [expression, alias] of this.expressions()) {
33
- const value: any = expression.value();
32
+ for (const [expression, alias] of this.expressions()) {
33
+ const raw = expression.value();
34
+ const value: any = typeof raw === "object" && raw !== null ? structuredClone(raw) : raw;
34
35
  record.set(alias, value);
35
36
  }
36
37
  this._results.push(Object.fromEntries(record));
37
38
  }
39
+ public async initialize(): Promise<void> {
40
+ this._results = [];
41
+ }
38
42
  public get results(): Record<string, any>[] {
39
43
  return this._results;
40
44
  }
41
45
  }
42
46
 
43
- export default Return;
47
+ export default Return;
@@ -1,12 +1,12 @@
1
- import Operation from "./operation";
2
1
  import Expression from "../expressions/expression";
2
+ import Operation from "./operation";
3
3
 
4
4
  /**
5
5
  * Represents a WHERE operation that filters data based on a condition.
6
- *
6
+ *
7
7
  * The WHERE operation evaluates a boolean expression and only continues
8
8
  * execution to the next operation if the condition is true.
9
- *
9
+ *
10
10
  * @example
11
11
  * ```typescript
12
12
  * // RETURN x WHERE x > 0
@@ -15,7 +15,7 @@ import Expression from "../expressions/expression";
15
15
  class Where extends Operation {
16
16
  /**
17
17
  * Creates a new WHERE operation with the given condition.
18
- *
18
+ *
19
19
  * @param expression - The boolean expression to evaluate
20
20
  */
21
21
  constructor(expression: Expression) {
@@ -26,7 +26,11 @@ class Where extends Operation {
26
26
  return this.children[0] as Expression;
27
27
  }
28
28
  public async run(): Promise<void> {
29
- if(this.expression.value()) {
29
+ for (const pattern of this.expression.patterns()) {
30
+ await pattern.fetchData();
31
+ await pattern.evaluate();
32
+ }
33
+ if (this.expression.value()) {
30
34
  await this.next?.run();
31
35
  }
32
36
  }
@@ -35,4 +39,4 @@ class Where extends Operation {
35
39
  }
36
40
  }
37
41
 
38
- export default Where;
42
+ export default Where;
@@ -1,3 +1,10 @@
1
+ import Hops from "../graph/hops";
2
+ import Node from "../graph/node";
3
+ import NodeReference from "../graph/node_reference";
4
+ import Pattern from "../graph/pattern";
5
+ import PatternExpression from "../graph/pattern_expression";
6
+ import Relationship from "../graph/relationship";
7
+ import RelationshipReference from "../graph/relationship_reference";
1
8
  import Token from "../tokenization/token";
2
9
  import ObjectUtils from "../utils/object_utils";
3
10
  import Alias from "./alias";
@@ -32,8 +39,11 @@ import When from "./logic/when";
32
39
  import AggregatedReturn from "./operations/aggregated_return";
33
40
  import AggregatedWith from "./operations/aggregated_with";
34
41
  import Call from "./operations/call";
42
+ import CreateNode from "./operations/create_node";
43
+ import CreateRelationship from "./operations/create_relationship";
35
44
  import Limit from "./operations/limit";
36
45
  import Load from "./operations/load";
46
+ import Match from "./operations/match";
37
47
  import Operation from "./operations/operation";
38
48
  import Return from "./operations/return";
39
49
  import Unwind from "./operations/unwind";
@@ -72,6 +82,10 @@ class Parser extends BaseParser {
72
82
  */
73
83
  public parse(statement: string): ASTNode {
74
84
  this.tokenize(statement);
85
+ return this._parseTokenized();
86
+ }
87
+
88
+ private _parseTokenized(isSubQuery: boolean = false): ASTNode {
75
89
  const root: ASTNode = new ASTNode();
76
90
  let previous: Operation | null = null;
77
91
  let operation: Operation | null = null;
@@ -82,8 +96,10 @@ class Parser extends BaseParser {
82
96
  this.skipWhitespaceAndComments();
83
97
  }
84
98
  operation = this.parseOperation();
85
- if (operation === null) {
99
+ if (operation === null && !isSubQuery) {
86
100
  throw new Error("Expected one of WITH, UNWIND, RETURN, LOAD, OR CALL");
101
+ } else if (operation === null && isSubQuery) {
102
+ return root;
87
103
  }
88
104
  if (this._returns > 1) {
89
105
  throw new Error("Only one RETURN statement is allowed");
@@ -94,28 +110,33 @@ class Parser extends BaseParser {
94
110
  );
95
111
  }
96
112
  if (previous !== null) {
97
- previous.addSibling(operation);
113
+ previous.addSibling(operation!);
98
114
  } else {
99
- root.addChild(operation);
115
+ root.addChild(operation!);
100
116
  }
101
117
  const where = this.parseWhere();
102
118
  if (where !== null) {
103
119
  if (operation instanceof Return) {
104
120
  (operation as Return).where = where;
105
121
  } else {
106
- operation.addSibling(where);
122
+ operation!.addSibling(where);
107
123
  operation = where;
108
124
  }
109
125
  }
110
126
  const limit = this.parseLimit();
111
127
  if (limit !== null) {
112
- operation.addSibling(limit);
128
+ operation!.addSibling(limit);
113
129
  operation = limit;
114
130
  }
115
131
  previous = operation;
116
132
  }
117
- if (!(operation instanceof Return) && !(operation instanceof Call)) {
118
- throw new Error("Last statement must be a RETURN, WHERE, or a CALL statement");
133
+ if (
134
+ !(operation instanceof Return) &&
135
+ !(operation instanceof Call) &&
136
+ !(operation instanceof CreateNode) &&
137
+ !(operation instanceof CreateRelationship)
138
+ ) {
139
+ throw new Error("Last statement must be a RETURN, WHERE, CALL, or CREATE statement");
119
140
  }
120
141
  return root;
121
142
  }
@@ -126,7 +147,9 @@ class Parser extends BaseParser {
126
147
  this.parseUnwind() ||
127
148
  this.parseReturn() ||
128
149
  this.parseLoad() ||
129
- this.parseCall()
150
+ this.parseCall() ||
151
+ this.parseCreate() ||
152
+ this.parseMatch()
130
153
  );
131
154
  }
132
155
 
@@ -307,6 +330,315 @@ class Parser extends BaseParser {
307
330
  return call;
308
331
  }
309
332
 
333
+ private parseCreate(): CreateNode | CreateRelationship | null {
334
+ if (!this.token.isCreate()) {
335
+ return null;
336
+ }
337
+ this.setNextToken();
338
+ this.expectAndSkipWhitespaceAndComments();
339
+ if (!this.token.isVirtual()) {
340
+ throw new Error("Expected VIRTUAL");
341
+ }
342
+ this.setNextToken();
343
+ this.expectAndSkipWhitespaceAndComments();
344
+ const node: Node | null = this.parseNode();
345
+ if (node === null) {
346
+ throw new Error("Expected node definition");
347
+ }
348
+ let relationship: Relationship | null = null;
349
+ if (this.token.isSubtract() && this.peek()?.isOpeningBracket()) {
350
+ this.setNextToken();
351
+ this.setNextToken();
352
+ if (!this.token.isColon()) {
353
+ throw new Error("Expected ':' for relationship type");
354
+ }
355
+ this.setNextToken();
356
+ if (!this.token.isIdentifier()) {
357
+ throw new Error("Expected relationship type identifier");
358
+ }
359
+ const type: string = this.token.value || "";
360
+ this.setNextToken();
361
+ if (!this.token.isClosingBracket()) {
362
+ throw new Error("Expected closing bracket for relationship definition");
363
+ }
364
+ this.setNextToken();
365
+ if (!this.token.isSubtract()) {
366
+ throw new Error("Expected '-' for relationship definition");
367
+ }
368
+ this.setNextToken();
369
+ const target: Node | null = this.parseNode();
370
+ if (target === null) {
371
+ throw new Error("Expected target node definition");
372
+ }
373
+ relationship = new Relationship();
374
+ relationship.type = type;
375
+ }
376
+ this.expectAndSkipWhitespaceAndComments();
377
+ if (!this.token.isAs()) {
378
+ throw new Error("Expected AS");
379
+ }
380
+ this.setNextToken();
381
+ this.expectAndSkipWhitespaceAndComments();
382
+ const query: ASTNode | null = this.parseSubQuery();
383
+ if (query === null) {
384
+ throw new Error("Expected sub-query");
385
+ }
386
+ let create: CreateNode | CreateRelationship;
387
+ if (relationship !== null) {
388
+ create = new CreateRelationship(relationship, query);
389
+ } else {
390
+ create = new CreateNode(node, query);
391
+ }
392
+ return create;
393
+ }
394
+
395
+ private parseMatch(): Match | null {
396
+ if (!this.token.isMatch()) {
397
+ return null;
398
+ }
399
+ this.setNextToken();
400
+ this.expectAndSkipWhitespaceAndComments();
401
+ const patterns: Pattern[] = Array.from(this.parsePatterns());
402
+ if (patterns.length === 0) {
403
+ throw new Error("Expected graph pattern");
404
+ }
405
+ return new Match(patterns);
406
+ }
407
+
408
+ private parseNode(): Node | null {
409
+ if (!this.token.isLeftParenthesis()) {
410
+ return null;
411
+ }
412
+ this.setNextToken();
413
+ this.skipWhitespaceAndComments();
414
+ let identifier: string | null = null;
415
+ if (this.token.isIdentifier()) {
416
+ identifier = this.token.value || "";
417
+ this.setNextToken();
418
+ }
419
+ this.skipWhitespaceAndComments();
420
+ let label: string | null = null;
421
+ if (!this.token.isColon() && this.peek()?.isIdentifier()) {
422
+ throw new Error("Expected ':' for node label");
423
+ }
424
+ if (this.token.isColon() && !this.peek()?.isIdentifier()) {
425
+ throw new Error("Expected node label identifier");
426
+ }
427
+ if (this.token.isColon() && this.peek()?.isIdentifier()) {
428
+ this.setNextToken();
429
+ label = this.token.value || "";
430
+ this.setNextToken();
431
+ }
432
+ this.skipWhitespaceAndComments();
433
+ let node = new Node();
434
+ node.label = label!;
435
+ if (label !== null && identifier !== null) {
436
+ node.identifier = identifier;
437
+ this.variables.set(identifier, node);
438
+ } else if (identifier !== null) {
439
+ const reference = this.variables.get(identifier);
440
+ if (reference === undefined || reference.constructor !== Node) {
441
+ throw new Error(`Undefined node reference: ${identifier}`);
442
+ }
443
+ node = new NodeReference(node, reference);
444
+ }
445
+ if (!this.token.isRightParenthesis()) {
446
+ throw new Error("Expected closing parenthesis for node definition");
447
+ }
448
+ this.setNextToken();
449
+ return node;
450
+ }
451
+
452
+ private *parsePatterns(): IterableIterator<Pattern> {
453
+ while (true) {
454
+ let identifier: string | null = null;
455
+ if (this.token.isIdentifier()) {
456
+ identifier = this.token.value || "";
457
+ this.setNextToken();
458
+ this.skipWhitespaceAndComments();
459
+ if (!this.token.isEquals()) {
460
+ throw new Error("Expected '=' for pattern assignment");
461
+ }
462
+ this.setNextToken();
463
+ this.skipWhitespaceAndComments();
464
+ }
465
+ const pattern: Pattern | null = this.parsePattern();
466
+ if (pattern !== null) {
467
+ if (identifier !== null) {
468
+ pattern.identifier = identifier;
469
+ this.variables.set(identifier, pattern);
470
+ }
471
+ yield pattern;
472
+ } else {
473
+ break;
474
+ }
475
+ this.skipWhitespaceAndComments();
476
+ if (!this.token.isComma()) {
477
+ break;
478
+ }
479
+ this.setNextToken();
480
+ this.skipWhitespaceAndComments();
481
+ }
482
+ }
483
+
484
+ private parsePattern(): Pattern | null {
485
+ if (!this.token.isLeftParenthesis()) {
486
+ return null;
487
+ }
488
+ const pattern = new Pattern();
489
+ let node = this.parseNode();
490
+ if (node === null) {
491
+ throw new Error("Expected node definition");
492
+ }
493
+ pattern.addElement(node);
494
+ let relationship: Relationship | null = null;
495
+ while (true) {
496
+ relationship = this.parseRelationship();
497
+ if (relationship === null) {
498
+ break;
499
+ }
500
+ pattern.addElement(relationship);
501
+ node = this.parseNode();
502
+ if (node === null) {
503
+ throw new Error("Expected target node definition");
504
+ }
505
+ pattern.addElement(node);
506
+ }
507
+ return pattern;
508
+ }
509
+
510
+ private parsePatternExpression(): PatternExpression | null {
511
+ if (!this.token.isLeftParenthesis()) {
512
+ return null;
513
+ }
514
+ const pattern = new PatternExpression();
515
+ let node = this.parseNode();
516
+ if (node === null) {
517
+ throw new Error("Expected node definition");
518
+ }
519
+ if (!(node instanceof NodeReference)) {
520
+ throw new Error("PatternExpression must start with a NodeReference");
521
+ }
522
+ pattern.addElement(node);
523
+ let relationship: Relationship | null = null;
524
+ while (true) {
525
+ relationship = this.parseRelationship();
526
+ if (relationship === null) {
527
+ break;
528
+ }
529
+ if (relationship.hops?.multi()) {
530
+ throw new Error("PatternExpression does not support variable-length relationships");
531
+ }
532
+ pattern.addElement(relationship);
533
+ node = this.parseNode();
534
+ if (node === null) {
535
+ throw new Error("Expected target node definition");
536
+ }
537
+ pattern.addElement(node);
538
+ }
539
+ return pattern;
540
+ }
541
+
542
+ private parseRelationship(): Relationship | null {
543
+ if (this.token.isLessThan() && this.peek()?.isSubtract()) {
544
+ this.setNextToken();
545
+ this.setNextToken();
546
+ } else if (this.token.isSubtract()) {
547
+ this.setNextToken();
548
+ } else {
549
+ return null;
550
+ }
551
+ if (!this.token.isOpeningBracket()) {
552
+ return null;
553
+ }
554
+ this.setNextToken();
555
+ let variable: string | null = null;
556
+ if (this.token.isIdentifier()) {
557
+ variable = this.token.value || "";
558
+ this.setNextToken();
559
+ }
560
+ if (!this.token.isColon()) {
561
+ throw new Error("Expected ':' for relationship type");
562
+ }
563
+ this.setNextToken();
564
+ if (!this.token.isIdentifier()) {
565
+ throw new Error("Expected relationship type identifier");
566
+ }
567
+ const type: string = this.token.value || "";
568
+ this.setNextToken();
569
+ const hops: Hops | null = this.parseRelationshipHops();
570
+ if (!this.token.isClosingBracket()) {
571
+ throw new Error("Expected closing bracket for relationship definition");
572
+ }
573
+ this.setNextToken();
574
+ if (!this.token.isSubtract()) {
575
+ throw new Error("Expected '-' for relationship definition");
576
+ }
577
+ this.setNextToken();
578
+ if (this.token.isGreaterThan()) {
579
+ this.setNextToken();
580
+ }
581
+ let relationship = new Relationship();
582
+ if (type !== null && variable !== null) {
583
+ relationship.identifier = variable;
584
+ this.variables.set(variable, relationship);
585
+ } else if (variable !== null) {
586
+ const reference = this.variables.get(variable);
587
+ if (reference === undefined || reference.constructor !== Relationship) {
588
+ throw new Error(`Undefined relationship reference: ${variable}`);
589
+ }
590
+ relationship = new RelationshipReference(relationship, reference);
591
+ }
592
+ if (hops !== null) {
593
+ relationship.hops = hops;
594
+ }
595
+ relationship.type = type;
596
+ return relationship;
597
+ }
598
+
599
+ private parseRelationshipHops(): Hops | null {
600
+ if (!this.token.isMultiply()) {
601
+ return null;
602
+ }
603
+ const hops = new Hops();
604
+ this.setNextToken();
605
+ if (this.token.isNumber()) {
606
+ hops.min = parseInt(this.token.value || "0");
607
+ this.setNextToken();
608
+ if (this.token.isDot()) {
609
+ this.setNextToken();
610
+ if (!this.token.isDot()) {
611
+ throw new Error("Expected '..' for relationship hops");
612
+ }
613
+ this.setNextToken();
614
+ if (!this.token.isNumber()) {
615
+ throw new Error("Expected number for relationship hops");
616
+ }
617
+ hops.max = parseInt(this.token.value || "0");
618
+ this.setNextToken();
619
+ }
620
+ } else {
621
+ hops.min = 0;
622
+ hops.max = Number.MAX_SAFE_INTEGER;
623
+ }
624
+ return hops;
625
+ }
626
+
627
+ private parseSubQuery(): ASTNode | null {
628
+ if (!this.token.isOpeningBrace()) {
629
+ return null;
630
+ }
631
+ this.setNextToken();
632
+ this.expectAndSkipWhitespaceAndComments();
633
+ const query: ASTNode = this._parseTokenized(true);
634
+ this.skipWhitespaceAndComments();
635
+ if (!this.token.isClosingBrace()) {
636
+ throw new Error("Expected closing brace for sub-query");
637
+ }
638
+ this.setNextToken();
639
+ return query;
640
+ }
641
+
310
642
  private parseLimit(): Limit | null {
311
643
  this.skipWhitespaceAndComments();
312
644
  if (!this.token.isLimit()) {
@@ -377,6 +709,12 @@ class Parser extends BaseParser {
377
709
  const lookup = this.parseLookup(func);
378
710
  expression.addNode(lookup);
379
711
  }
712
+ } else if (this.token.isLeftParenthesis() && this.peek()?.isIdentifier()) {
713
+ // Possible graph pattern expression
714
+ const pattern = this.parsePatternExpression();
715
+ if (pattern !== null) {
716
+ expression.addNode(pattern);
717
+ }
380
718
  } else if (this.token.isOperand()) {
381
719
  expression.addNode(this.token.node);
382
720
  this.setNextToken();
@@ -4,6 +4,7 @@ import CSV from "./components/csv";
4
4
  import JSON from "./components/json";
5
5
  import Null from "./components/null";
6
6
  import Text from "./components/text";
7
+ import Boolean from "./expressions/boolean";
7
8
  import Identifier from "./expressions/identifier";
8
9
  import Number from "./expressions/number";
9
10
  import {
@@ -19,6 +20,7 @@ import {
19
20
  Modulo,
20
21
  Multiply,
21
22
  Not,
23
+ NotEquals,
22
24
  Or,
23
25
  Power,
24
26
  Subtract,
@@ -61,6 +63,8 @@ class TokenToNode {
61
63
  return new Power();
62
64
  } else if (token.isEquals()) {
63
65
  return new Equals();
66
+ } else if (token.isNotEquals()) {
67
+ return new NotEquals();
64
68
  } else if (token.isLessThan()) {
65
69
  return new LessThan();
66
70
  } else if (token.isGreaterThan()) {
@@ -98,6 +102,8 @@ class TokenToNode {
98
102
  } else if (token.isNull()) {
99
103
  return new Null();
100
104
  }
105
+ } else if (token.isBoolean()) {
106
+ return new Boolean(token.value!);
101
107
  } else {
102
108
  throw new Error("Unknown token");
103
109
  }
@@ -1,43 +1,44 @@
1
1
  enum Keyword {
2
- RETURN = 'RETURN',
3
- MATCH = 'MATCH',
4
- WHERE = 'WHERE',
5
- CREATE = 'CREATE',
6
- MERGE = 'MERGE',
7
- DELETE = 'DELETE',
8
- DETACH = 'DETACH',
9
- SET = 'SET',
10
- REMOVE = 'REMOVE',
11
- FOREACH = 'FOREACH',
12
- WITH = 'WITH',
13
- CALL = 'CALL',
14
- YIELD = 'YIELD',
15
- LOAD = 'LOAD',
16
- HEADERS = 'HEADERS',
17
- POST = 'POST',
18
- FROM = 'FROM',
19
- CSV = 'CSV',
20
- JSON = 'JSON',
21
- TEXT = 'TEXT',
22
- AS = 'AS',
23
- UNWIND = 'UNWIND',
24
- SUM = 'SUM',
25
- COLLECT = 'COLLECT',
26
- DISTINCT = 'DISTINCT',
27
- ORDER = 'ORDER',
28
- BY = 'BY',
29
- ASC = 'ASC',
30
- DESC = 'DESC',
31
- SKIP = 'SKIP',
32
- LIMIT = 'LIMIT',
33
- EOF = 'EOF',
34
- CASE = 'CASE',
35
- WHEN = 'WHEN',
36
- THEN = 'THEN',
37
- ELSE = 'ELSE',
38
- END = 'END',
39
- NULL = 'NULL',
40
- IN = 'IN',
2
+ RETURN = "RETURN",
3
+ MATCH = "MATCH",
4
+ WHERE = "WHERE",
5
+ CREATE = "CREATE",
6
+ VIRTUAL = "VIRTUAL",
7
+ MERGE = "MERGE",
8
+ DELETE = "DELETE",
9
+ DETACH = "DETACH",
10
+ SET = "SET",
11
+ REMOVE = "REMOVE",
12
+ FOREACH = "FOREACH",
13
+ WITH = "WITH",
14
+ CALL = "CALL",
15
+ YIELD = "YIELD",
16
+ LOAD = "LOAD",
17
+ HEADERS = "HEADERS",
18
+ POST = "POST",
19
+ FROM = "FROM",
20
+ CSV = "CSV",
21
+ JSON = "JSON",
22
+ TEXT = "TEXT",
23
+ AS = "AS",
24
+ UNWIND = "UNWIND",
25
+ SUM = "SUM",
26
+ COLLECT = "COLLECT",
27
+ DISTINCT = "DISTINCT",
28
+ ORDER = "ORDER",
29
+ BY = "BY",
30
+ ASC = "ASC",
31
+ DESC = "DESC",
32
+ SKIP = "SKIP",
33
+ LIMIT = "LIMIT",
34
+ EOF = "EOF",
35
+ CASE = "CASE",
36
+ WHEN = "WHEN",
37
+ THEN = "THEN",
38
+ ELSE = "ELSE",
39
+ END = "END",
40
+ NULL = "NULL",
41
+ IN = "IN",
41
42
  }
42
43
 
43
- export default Keyword;
44
+ export default Keyword;
@@ -143,6 +143,18 @@ class Token {
143
143
  return this._type === TokenType.NUMBER;
144
144
  }
145
145
 
146
+ // Boolean token
147
+
148
+ public static BOOLEAN(value: string): Token {
149
+ return new Token(TokenType.BOOLEAN, value);
150
+ }
151
+
152
+ public isBoolean(): boolean {
153
+ return (
154
+ this._type === TokenType.BOOLEAN && (this._value === "TRUE" || this._value === "FALSE")
155
+ );
156
+ }
157
+
146
158
  // Symbol tokens
147
159
 
148
160
  public static get LEFT_PARENTHESIS(): Token {
@@ -511,6 +523,14 @@ class Token {
511
523
  return this._type === TokenType.KEYWORD && this._value === Keyword.CREATE;
512
524
  }
513
525
 
526
+ public static get VIRTUAL(): Token {
527
+ return new Token(TokenType.KEYWORD, Keyword.VIRTUAL);
528
+ }
529
+
530
+ public isVirtual(): boolean {
531
+ return this._type === TokenType.KEYWORD && this._value === Keyword.VIRTUAL;
532
+ }
533
+
514
534
  public static get DELETE(): Token {
515
535
  return new Token(TokenType.KEYWORD, Keyword.DELETE);
516
536
  }
@@ -628,7 +648,7 @@ class Token {
628
648
  // Other utility methods
629
649
 
630
650
  public isOperand(): boolean {
631
- return this.isNumber() || this.isString() || this.isNull();
651
+ return this.isNumber() || this.isBoolean() || this.isString() || this.isNull();
632
652
  }
633
653
 
634
654
  public isWhitespaceOrComment(): boolean {