flowquery 1.0.68 → 1.0.70
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/README.md +244 -1
- package/dist/compute/runner.d.ts +6 -0
- package/dist/compute/runner.d.ts.map +1 -1
- package/dist/compute/runner.js +26 -0
- package/dist/compute/runner.js.map +1 -1
- package/dist/flowquery.min.js +1 -1
- package/dist/graph/bindings.d.ts +78 -0
- package/dist/graph/bindings.d.ts.map +1 -0
- package/dist/graph/bindings.js +210 -0
- package/dist/graph/bindings.js.map +1 -0
- package/dist/graph/database.d.ts +4 -2
- package/dist/graph/database.d.ts.map +1 -1
- package/dist/graph/database.js +45 -9
- package/dist/graph/database.js.map +1 -1
- package/dist/graph/physical_node.d.ts +9 -0
- package/dist/graph/physical_node.d.ts.map +1 -1
- package/dist/graph/physical_node.js +70 -3
- package/dist/graph/physical_node.js.map +1 -1
- package/dist/graph/physical_relationship.d.ts +9 -0
- package/dist/graph/physical_relationship.d.ts.map +1 -1
- package/dist/graph/physical_relationship.js +70 -3
- package/dist/graph/physical_relationship.js.map +1 -1
- package/dist/parsing/ast_node.d.ts +9 -0
- package/dist/parsing/ast_node.d.ts.map +1 -1
- package/dist/parsing/ast_node.js +21 -4
- package/dist/parsing/ast_node.js.map +1 -1
- package/dist/parsing/expressions/binding_reference.d.ts +16 -0
- package/dist/parsing/expressions/binding_reference.d.ts.map +1 -0
- package/dist/parsing/expressions/binding_reference.js +34 -0
- package/dist/parsing/expressions/binding_reference.js.map +1 -0
- package/dist/parsing/operations/create_node.d.ts +5 -1
- package/dist/parsing/operations/create_node.d.ts.map +1 -1
- package/dist/parsing/operations/create_node.js +12 -2
- package/dist/parsing/operations/create_node.js.map +1 -1
- package/dist/parsing/operations/create_relationship.d.ts +5 -1
- package/dist/parsing/operations/create_relationship.d.ts.map +1 -1
- package/dist/parsing/operations/create_relationship.js +12 -2
- package/dist/parsing/operations/create_relationship.js.map +1 -1
- package/dist/parsing/operations/drop_binding.d.ts +15 -0
- package/dist/parsing/operations/drop_binding.d.ts.map +1 -0
- package/dist/parsing/operations/drop_binding.js +42 -0
- package/dist/parsing/operations/drop_binding.js.map +1 -0
- package/dist/parsing/operations/let.d.ts +36 -0
- package/dist/parsing/operations/let.d.ts.map +1 -0
- package/dist/parsing/operations/let.js +101 -0
- package/dist/parsing/operations/let.js.map +1 -0
- package/dist/parsing/operations/load.d.ts +11 -0
- package/dist/parsing/operations/load.d.ts.map +1 -1
- package/dist/parsing/operations/load.js +31 -2
- package/dist/parsing/operations/load.js.map +1 -1
- package/dist/parsing/operations/merge.d.ts +158 -0
- package/dist/parsing/operations/merge.d.ts.map +1 -0
- package/dist/parsing/operations/merge.js +338 -0
- package/dist/parsing/operations/merge.js.map +1 -0
- package/dist/parsing/operations/refresh_binding.d.ts +15 -0
- package/dist/parsing/operations/refresh_binding.d.ts.map +1 -0
- package/dist/parsing/operations/refresh_binding.js +42 -0
- package/dist/parsing/operations/refresh_binding.js.map +1 -0
- package/dist/parsing/operations/refresh_node.d.ts +11 -0
- package/dist/parsing/operations/refresh_node.d.ts.map +1 -0
- package/dist/parsing/operations/refresh_node.js +46 -0
- package/dist/parsing/operations/refresh_node.js.map +1 -0
- package/dist/parsing/operations/refresh_relationship.d.ts +11 -0
- package/dist/parsing/operations/refresh_relationship.d.ts.map +1 -0
- package/dist/parsing/operations/refresh_relationship.js +46 -0
- package/dist/parsing/operations/refresh_relationship.js.map +1 -0
- package/dist/parsing/operations/return.d.ts.map +1 -1
- package/dist/parsing/operations/return.js +7 -1
- package/dist/parsing/operations/return.js.map +1 -1
- package/dist/parsing/operations/update.d.ts +27 -0
- package/dist/parsing/operations/update.d.ts.map +1 -0
- package/dist/parsing/operations/update.js +88 -0
- package/dist/parsing/operations/update.js.map +1 -0
- package/dist/parsing/operations/update_delete.d.ts +43 -0
- package/dist/parsing/operations/update_delete.d.ts.map +1 -0
- package/dist/parsing/operations/update_delete.js +105 -0
- package/dist/parsing/operations/update_delete.js.map +1 -0
- package/dist/parsing/parser.d.ts +70 -1
- package/dist/parsing/parser.d.ts.map +1 -1
- package/dist/parsing/parser.js +704 -10
- package/dist/parsing/parser.js.map +1 -1
- package/dist/parsing/statement_info_crawler.d.ts +26 -0
- package/dist/parsing/statement_info_crawler.d.ts.map +1 -1
- package/dist/parsing/statement_info_crawler.js +86 -4
- package/dist/parsing/statement_info_crawler.js.map +1 -1
- package/dist/tokenization/keyword.d.ts +21 -1
- package/dist/tokenization/keyword.d.ts.map +1 -1
- package/dist/tokenization/keyword.js +20 -0
- package/dist/tokenization/keyword.js.map +1 -1
- package/dist/tokenization/token.d.ts +24 -0
- package/dist/tokenization/token.d.ts.map +1 -1
- package/dist/tokenization/token.js +73 -0
- package/dist/tokenization/token.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -227,7 +227,7 @@ WITH 1 AS x RETURN x UNION ALL WITH 1 AS x RETURN x
|
|
|
227
227
|
|
|
228
228
|
#### Multi-Statement Queries
|
|
229
229
|
|
|
230
|
-
Multiple statements can be separated by semicolons. Only `CREATE VIRTUAL`
|
|
230
|
+
Multiple statements can be separated by semicolons. Only declaration statements — `CREATE VIRTUAL`, `DELETE VIRTUAL` (alias: `DROP VIRTUAL`), `REFRESH VIRTUAL`, `LET`, `UPDATE`, and `MERGE INTO` — may appear before the last statement. The last statement can be any valid query.
|
|
231
231
|
|
|
232
232
|
```cypher
|
|
233
233
|
CREATE VIRTUAL (:Person) AS {
|
|
@@ -253,6 +253,97 @@ console.log(runner.metadata);
|
|
|
253
253
|
// info: { node_labels: ["X"], relationship_types: [], sources: [], ... } }
|
|
254
254
|
```
|
|
255
255
|
|
|
256
|
+
#### Caching Virtual Entities: `STATIC` and `REFRESH`
|
|
257
|
+
|
|
258
|
+
By default, every `MATCH` against a virtual node or relationship re-executes
|
|
259
|
+
its backing sub-query. For expensive sources (HTTP endpoints, large CSV files)
|
|
260
|
+
you can opt in to persistent caching with the `STATIC` keyword:
|
|
261
|
+
|
|
262
|
+
```cypher
|
|
263
|
+
CREATE STATIC VIRTUAL (:Country) AS {
|
|
264
|
+
LOAD JSON FROM 'https://restcountries.com/v3.1/all?fields=name,cca2,population' AS c
|
|
265
|
+
RETURN c.cca2 AS code, c.name.common AS name
|
|
266
|
+
};
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
The sub-query runs once on first access and the result is reused for every
|
|
270
|
+
subsequent query in the same process — across `Runner` instances. STATIC
|
|
271
|
+
virtual entities are protected: re-running `CREATE STATIC VIRTUAL (:Country)`
|
|
272
|
+
without first dropping the existing entry raises an error. Use
|
|
273
|
+
`DROP VIRTUAL (:Country)` (an alias for `DELETE VIRTUAL`) to remove it.
|
|
274
|
+
|
|
275
|
+
To refresh on a schedule, add a `REFRESH EVERY <n> <unit>` clause. Supported
|
|
276
|
+
units are `SECOND[S]`, `MINUTE[S]`, `HOUR[S]`, and `DAY[S]`:
|
|
277
|
+
|
|
278
|
+
```cypher
|
|
279
|
+
CREATE STATIC VIRTUAL (:Country) AS {
|
|
280
|
+
LOAD JSON FROM 'https://restcountries.com/v3.1/all?fields=name,cca2,population' AS c
|
|
281
|
+
RETURN c.cca2 AS code, c.name.common AS name
|
|
282
|
+
} REFRESH EVERY 1 HOUR;
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Refresh is lazy: the cache is re-populated on the first access after the TTL
|
|
286
|
+
elapses; no background timers are scheduled. `REFRESH EVERY` requires
|
|
287
|
+
`STATIC` (caching must be enabled to refresh).
|
|
288
|
+
|
|
289
|
+
To force an immediate refresh from anywhere in a query, use
|
|
290
|
+
`REFRESH VIRTUAL (...)`:
|
|
291
|
+
|
|
292
|
+
```cypher
|
|
293
|
+
REFRESH VIRTUAL (:Country);
|
|
294
|
+
MATCH (c:Country) RETURN c.name
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
`REFRESH VIRTUAL` works on both nodes and relationships and clears the cache
|
|
298
|
+
so that the next access re-executes the backing sub-query.
|
|
299
|
+
|
|
300
|
+
#### Refreshable `LET` Bindings: `REFRESH EVERY`, `REFRESH BINDING`, `DROP BINDING`
|
|
301
|
+
|
|
302
|
+
`LET` bindings live for the lifetime of the process, just like virtual
|
|
303
|
+
nodes and relationships, and the same caching primitives apply. A plain
|
|
304
|
+
`LET name = { ... }` evaluates the sub-query once, when the `LET`
|
|
305
|
+
statement executes, and stores the result in the global binding store;
|
|
306
|
+
all subsequent reads return that cached value without re-running the
|
|
307
|
+
sub-query. To opt into TTL-based re-evaluation, add a trailing
|
|
308
|
+
`REFRESH EVERY <n> <unit>` clause:
|
|
309
|
+
|
|
310
|
+
```cypher
|
|
311
|
+
LET users = {
|
|
312
|
+
LOAD JSON FROM 'https://example.com/users.json' AS u
|
|
313
|
+
RETURN u.id AS id, u.name AS name
|
|
314
|
+
} REFRESH EVERY 5 MINUTES;
|
|
315
|
+
LOAD JSON FROM users AS u RETURN u.id AS id, u.name AS name
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
The sub-query still runs eagerly at `LET` time and the result is cached
|
|
319
|
+
just like a plain binding; the `REFRESH EVERY` clause additionally
|
|
320
|
+
arranges for the next read after the TTL has elapsed to re-execute the
|
|
321
|
+
sub-query.
|
|
322
|
+
|
|
323
|
+
Refreshable bindings (those with a `REFRESH EVERY` clause) cannot be
|
|
324
|
+
silently overwritten: re-running `LET name = { ... } REFRESH EVERY ...`
|
|
325
|
+
without first dropping the existing binding raises an error, and so
|
|
326
|
+
does `UPDATE name = ...` or `MERGE INTO name ...` against the same
|
|
327
|
+
name. `LET ... REFRESH EVERY` requires a sub-query right-hand side
|
|
328
|
+
(an expression like `42 REFRESH EVERY 1 MINUTE` is rejected). To force
|
|
329
|
+
an immediate refresh outside the TTL schedule, use `REFRESH BINDING`:
|
|
330
|
+
|
|
331
|
+
```cypher
|
|
332
|
+
REFRESH BINDING users;
|
|
333
|
+
LOAD JSON FROM users AS u RETURN u.id AS id
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
To remove any binding (plain or refreshable), use `DROP BINDING`:
|
|
337
|
+
|
|
338
|
+
```cypher
|
|
339
|
+
DROP BINDING users;
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
`UPDATE` and `MERGE INTO` against a refreshable binding are blocked
|
|
343
|
+
because the mutation would be invisibly overwritten by the next
|
|
344
|
+
refresh. Use `REFRESH BINDING name` to re-evaluate the source, or
|
|
345
|
+
`DROP BINDING name` and redefine the binding plainly.
|
|
346
|
+
|
|
256
347
|
#### Statement Info: Labels, Properties, and Source Lineage
|
|
257
348
|
|
|
258
349
|
`metadata.info` carries a `StatementInfo` describing the _structure_ the
|
|
@@ -391,6 +482,115 @@ UNWIND [1, 1, 2, 2] AS i RETURN DISTINCT i
|
|
|
391
482
|
// [{ i: 1 }, { i: 2 }]
|
|
392
483
|
```
|
|
393
484
|
|
|
485
|
+
### Bindings (`LET` / `UPDATE` / `MERGE INTO`)
|
|
486
|
+
|
|
487
|
+
A **binding** is a named, mutable value that persists across statements in a multi-statement query. Bindings live in a flat per-query namespace, are introduced with `LET`, wholesale-replaced with `UPDATE`, row-filtered with `UPDATE … AS x DELETE WHERE …`, and per-row upserted/merged with `MERGE INTO … USING … ON … WHEN …`. Once bound, the value can be referenced anywhere an expression is allowed (e.g. as the source of `LOAD JSON FROM`, `UNWIND`, `MERGE INTO`'s `USING`, or directly inside an expression).
|
|
488
|
+
|
|
489
|
+
#### LET
|
|
490
|
+
|
|
491
|
+
`LET name = <expression-or-subquery>` introduces a new binding. The right-hand side can be any expression or a braced sub-query whose final `RETURN` provides the value.
|
|
492
|
+
|
|
493
|
+
```cypher
|
|
494
|
+
LET data = [{id: 1, name: 'Alice'}, {id: 2, name: 'Bob'}];
|
|
495
|
+
LET threshold = 10;
|
|
496
|
+
LET fresh = {
|
|
497
|
+
UNWIND [1, 2, 3] AS n
|
|
498
|
+
RETURN n AS n
|
|
499
|
+
};
|
|
500
|
+
LOAD JSON FROM data AS d
|
|
501
|
+
WITH d WHERE d.id >= threshold OR d.id <= 2
|
|
502
|
+
RETURN d.id AS id, d.name AS name
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
`LET` fails if the binding already exists — use `UPDATE` to overwrite.
|
|
506
|
+
|
|
507
|
+
#### UPDATE
|
|
508
|
+
|
|
509
|
+
`UPDATE name = <expression-or-subquery>` replaces the value of an existing binding wholesale. Works for any value (scalars, maps, arrays).
|
|
510
|
+
|
|
511
|
+
```cypher
|
|
512
|
+
LET counter = 0;
|
|
513
|
+
UPDATE counter = counter + 1;
|
|
514
|
+
RETURN counter AS counter
|
|
515
|
+
// [{ counter: 1 }]
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
`UPDATE` fails if the binding doesn't exist — use `LET` first.
|
|
519
|
+
|
|
520
|
+
#### UPDATE ... AS alias DELETE WHERE ...
|
|
521
|
+
|
|
522
|
+
Filters rows out of an array binding in place. The alias names each row during predicate evaluation.
|
|
523
|
+
|
|
524
|
+
```cypher
|
|
525
|
+
LET users = [
|
|
526
|
+
{id: 1, name: 'Alice', expired: false},
|
|
527
|
+
{id: 2, name: 'Bob', expired: true}
|
|
528
|
+
];
|
|
529
|
+
UPDATE users AS u DELETE WHERE u.expired;
|
|
530
|
+
LOAD JSON FROM users AS u
|
|
531
|
+
RETURN u.id AS id, u.name AS name
|
|
532
|
+
// [{ id: 1, name: 'Alice' }]
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
#### MERGE INTO ... USING ... ON ... WHEN ...
|
|
536
|
+
|
|
537
|
+
SQL-style keyed merge. For each row of the source, find matching rows in the target (by key or predicate) and apply per-row branches:
|
|
538
|
+
|
|
539
|
+
```
|
|
540
|
+
MERGE INTO target [AS t]
|
|
541
|
+
USING <source-expression-or-subquery> [AS s]
|
|
542
|
+
ON <key-or-key-list> | <predicate>
|
|
543
|
+
[WHEN MATCHED THEN UPDATE SET <field-list>]
|
|
544
|
+
[WHEN MATCHED THEN DELETE]
|
|
545
|
+
[WHEN NOT MATCHED THEN INSERT [<row-expression>]]
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
```cypher
|
|
549
|
+
// Upsert by key: replace listed fields on matches; append unmatched source rows
|
|
550
|
+
LET users = [{id: 1, name: 'Alice'}, {id: 2, name: 'Bob'}];
|
|
551
|
+
MERGE INTO users
|
|
552
|
+
USING [{id: 2, name: 'Bobby'}, {id: 3, name: 'Charlie'}]
|
|
553
|
+
ON id
|
|
554
|
+
WHEN MATCHED THEN UPDATE SET .id, .name
|
|
555
|
+
WHEN NOT MATCHED THEN INSERT;
|
|
556
|
+
// users → [{id:1,name:'Alice'}, {id:2,name:'Bobby'}, {id:3,name:'Charlie'}]
|
|
557
|
+
|
|
558
|
+
// Composite key
|
|
559
|
+
MERGE INTO rows
|
|
560
|
+
USING incoming
|
|
561
|
+
ON (tenant, id)
|
|
562
|
+
WHEN MATCHED THEN UPDATE SET .v
|
|
563
|
+
WHEN NOT MATCHED THEN INSERT;
|
|
564
|
+
|
|
565
|
+
// Per-row expressions across target (u) and source (s) aliases
|
|
566
|
+
MERGE INTO users AS u
|
|
567
|
+
USING incoming AS s
|
|
568
|
+
ON id
|
|
569
|
+
WHEN MATCHED THEN UPDATE SET .name = s.name + ' (' + u.name + ')'
|
|
570
|
+
WHEN NOT MATCHED THEN INSERT {id: s.id, name: 'New: ' + s.name};
|
|
571
|
+
|
|
572
|
+
// Predicate-based join
|
|
573
|
+
MERGE INTO users AS u
|
|
574
|
+
USING incoming AS s
|
|
575
|
+
ON u.tenant = s.tenant AND u.email = s.email
|
|
576
|
+
WHEN MATCHED THEN UPDATE SET .v = s.v
|
|
577
|
+
WHEN NOT MATCHED THEN INSERT;
|
|
578
|
+
|
|
579
|
+
// Tombstone delete: rows in target that also appear in source are removed
|
|
580
|
+
MERGE INTO users
|
|
581
|
+
USING [{id: 2}, {id: 3}]
|
|
582
|
+
ON id
|
|
583
|
+
WHEN MATCHED THEN DELETE;
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
Notes:
|
|
587
|
+
|
|
588
|
+
- The source may be any expression (array literal, binding name) or a braced sub-query. When the source is a bare binding name, give it an alias: `USING incoming AS s`.
|
|
589
|
+
- `ON id` is shorthand for the equality predicate `t.id = s.id`; `ON (a, b)` requires equality on every listed key. Anything else is treated as a Boolean predicate evaluated per `(target, source)` pair.
|
|
590
|
+
- `WHEN MATCHED THEN UPDATE SET .field` overwrites only the listed fields, preserving the rest from the existing row. `SET .field = expr` evaluates `expr` per matched pair, with target and source aliases in scope.
|
|
591
|
+
- `WHEN NOT MATCHED THEN INSERT` (no row expression) appends the source row as-is. `INSERT { … }` appends an explicit row expression instead.
|
|
592
|
+
- A `MERGE INTO` must declare at least one `WHEN` clause. Branches are independent — omit `WHEN NOT MATCHED` to skip insertion, omit `WHEN MATCHED` to skip updates/deletes.
|
|
593
|
+
|
|
394
594
|
### Expressions
|
|
395
595
|
|
|
396
596
|
#### Arithmetic
|
|
@@ -832,6 +1032,18 @@ RETURN f.name, f.description, f.category
|
|
|
832
1032
|
│ stmt1; stmt2; ... stmtN -- multi-statement │
|
|
833
1033
|
│ LIMIT n │
|
|
834
1034
|
├─────────────────────────────────────────────────────────────┤
|
|
1035
|
+
│ BINDINGS │
|
|
1036
|
+
├─────────────────────────────────────────────────────────────┤
|
|
1037
|
+
│ LET name = expr | { subquery } -- new binding │
|
|
1038
|
+
│ UPDATE name = expr | { subquery } -- replace existing │
|
|
1039
|
+
│ UPDATE name AS x DELETE WHERE cond -- row-filter binding │
|
|
1040
|
+
│ MERGE INTO target [AS t] │
|
|
1041
|
+
│ USING <expr | subquery> [AS s] │
|
|
1042
|
+
│ ON key | (k1,k2,...) | predicate │
|
|
1043
|
+
│ [WHEN MATCHED THEN UPDATE SET .f [= expr], ...] │
|
|
1044
|
+
│ [WHEN MATCHED THEN DELETE] │
|
|
1045
|
+
│ [WHEN NOT MATCHED THEN INSERT [ {row-expr} ]] │
|
|
1046
|
+
├─────────────────────────────────────────────────────────────┤
|
|
835
1047
|
│ GRAPH OPERATIONS │
|
|
836
1048
|
├─────────────────────────────────────────────────────────────┤
|
|
837
1049
|
│ CREATE VIRTUAL (:Label) AS { subquery } │
|
|
@@ -1166,6 +1378,37 @@ RETURN a.name AS employee1, b.name AS employee2, shared AS sharedSkills
|
|
|
1166
1378
|
ORDER BY size(shared) DESC
|
|
1167
1379
|
```
|
|
1168
1380
|
|
|
1381
|
+
### Virtual Country Borders Graph
|
|
1382
|
+
|
|
1383
|
+
This example pulls live data from the public [REST Countries](https://restcountries.com/) API and projects it into a `(:Country)-[:BORDERS]-(:Country)` virtual graph in a single semicolon-chained query, then ranks European countries by how many direct neighbors they have. [Try live!](https://microsoft.github.io/FlowQuery/?nZBRa4MwFIXf8yvumx1YXelbRxlWM-qwCtGujDGKxrQVrJFoB2Xsv49Eq3Ure1iekuvxnu8cD0dA-amoRcYqmMMnAgDwAsuB5zDw4YkEK9AOdV1WM9MUrKo7tUH50fyYGhMzzvPHXcbytJoX8ZHplMZTXbB9xgu95OUpj2t5TbhImag0sEKgyofgaE18oIb8A9pjhZClOoL-UEOulX5HXsjvymWoaOy6Da37UNOzKM0V2lDXgl52tU_09YCQTbAVYXhxSbS2PBjNbFXH-U4Kb5bXt_s7dpa2aduIXbY-UJ9lGGDA_zfa-G22CIiDSfg-_h_w2t-4vnPVjGzlVpSc7eqtzJMo8Gx_kE-Ft7Iiewmj-DZW0o3RZokJhvhSwBw0fBK8ZBpqzeKuqwb1rDeXUaJCFSzbHxIutmqIlAUsXn_MwcGhjTx35UYwuf8G)
|
|
1384
|
+
|
|
1385
|
+
A single shared `LET` binding fetches the data once. Both virtuals (the `(:Country)` nodes and the `(:Country)-[:BORDERS]-(:Country)` relationships) are projected from the same binding, so there is exactly one HTTP round-trip per Runner invocation. Add `REFRESH EVERY 1 HOUR` to the `LET` if you want the cache to auto-refresh on a schedule.
|
|
1386
|
+
|
|
1387
|
+
```cypher
|
|
1388
|
+
LET countries = {
|
|
1389
|
+
LOAD JSON FROM 'https://restcountries.com/v3.1/all?fields=name,cca3,region,population,borders' AS c
|
|
1390
|
+
RETURN c.cca3 AS id,
|
|
1391
|
+
c.name.common AS name,
|
|
1392
|
+
c.region AS region,
|
|
1393
|
+
c.population AS population,
|
|
1394
|
+
c.borders AS borders
|
|
1395
|
+
};
|
|
1396
|
+
CREATE VIRTUAL (:Country) AS {
|
|
1397
|
+
LOAD JSON FROM countries AS c
|
|
1398
|
+
RETURN c.id AS id, c.name AS name, c.region AS region, c.population AS population
|
|
1399
|
+
};
|
|
1400
|
+
CREATE VIRTUAL (:Country)-[:BORDERS]-(:Country) AS {
|
|
1401
|
+
LOAD JSON FROM countries AS c
|
|
1402
|
+
UNWIND c.borders AS b
|
|
1403
|
+
RETURN c.id AS left_id, b AS right_id
|
|
1404
|
+
};
|
|
1405
|
+
MATCH (a:Country)-[:BORDERS]-(b:Country)
|
|
1406
|
+
WHERE a.region = 'Europe'
|
|
1407
|
+
RETURN a.name AS country, count(b) AS neighbor_count
|
|
1408
|
+
ORDER BY neighbor_count DESC
|
|
1409
|
+
LIMIT 10
|
|
1410
|
+
```
|
|
1411
|
+
|
|
1169
1412
|
## Contributing
|
|
1170
1413
|
|
|
1171
1414
|
This project welcomes contributions and suggestions. Most contributions require you to agree to a
|
package/dist/compute/runner.d.ts
CHANGED
|
@@ -73,6 +73,12 @@ declare class Runner {
|
|
|
73
73
|
* - $name resolves to args["name"] (shorthand for individual properties)
|
|
74
74
|
*/
|
|
75
75
|
private bindParameters;
|
|
76
|
+
/**
|
|
77
|
+
* Recursively walks the AST to collect the names of all
|
|
78
|
+
* `BindingReference`s. Used to refresh stale refreshable
|
|
79
|
+
* bindings before statement execution begins.
|
|
80
|
+
*/
|
|
81
|
+
private collectBindingNames;
|
|
76
82
|
/**
|
|
77
83
|
* Gets the results from the executed statement.
|
|
78
84
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/compute/runner.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/compute/runner.ts"],"names":[],"mappings":"AAGA,OAAO,OAAO,MAAM,qBAAqB,CAAC;AAS1C,OAA6B,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAExF,YAAY,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAEvE;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC3B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,6BAA6B,EAAE,MAAM,CAAC;IACtC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,6BAA6B,EAAE,MAAM,CAAC;IACtC;;;OAGG;IACH,IAAI,CAAC,EAAE,aAAa,CAAC;CACxB;AAQD;;;;;;;;;;;;;;;;;GAiBG;AACH,cAAM,MAAM;IACR,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,SAAS,CAAiB;IAElC;;;;;;;OAOG;gBAEC,SAAS,GAAE,MAAM,GAAG,IAAW,EAC/B,GAAG,GAAE,OAAO,GAAG,IAAW,EAC1B,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAW;IAqB3C,OAAO,CAAC,MAAM,CAAC,WAAW;IAQ1B;;;;OAIG;IACH,OAAO,CAAC,eAAe;IAqBvB;;;;;OAKG;IACU,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IA8BjC;;;;;OAKG;IACH,OAAO,CAAC,cAAc;IAetB;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAS3B;;;;OAIG;IACH,IAAW,OAAO,IAAI,GAAG,CAExB;IAED;;;;;OAKG;IACH,IAAW,QAAQ,IAAI,cAAc,CASpC;CACJ;AAED,eAAe,MAAM,CAAC"}
|
package/dist/compute/runner.js
CHANGED
|
@@ -12,8 +12,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const bindings_1 = __importDefault(require("../graph/bindings"));
|
|
15
16
|
const data_cache_1 = __importDefault(require("../graph/data_cache"));
|
|
16
17
|
const data_resolver_1 = __importDefault(require("../graph/data_resolver"));
|
|
18
|
+
const binding_reference_1 = __importDefault(require("../parsing/expressions/binding_reference"));
|
|
17
19
|
const parameter_reference_1 = __importDefault(require("../parsing/expressions/parameter_reference"));
|
|
18
20
|
const create_node_1 = __importDefault(require("../parsing/operations/create_node"));
|
|
19
21
|
const create_relationship_1 = __importDefault(require("../parsing/operations/create_relationship"));
|
|
@@ -115,6 +117,17 @@ class Runner {
|
|
|
115
117
|
}
|
|
116
118
|
for (const stmt of this._statements) {
|
|
117
119
|
this.bindParameters(stmt.ast);
|
|
120
|
+
// Refresh any stale refreshable bindings referenced
|
|
121
|
+
// by this statement. Sub-query evaluation is
|
|
122
|
+
// async, but BindingReference.value() is sync;
|
|
123
|
+
// populating the cache up-front keeps reads cheap
|
|
124
|
+
// and synchronous.
|
|
125
|
+
const bindingNames = new Set();
|
|
126
|
+
this.collectBindingNames(stmt.ast, bindingNames);
|
|
127
|
+
const bindings = bindings_1.default.getInstance();
|
|
128
|
+
for (const name of bindingNames) {
|
|
129
|
+
yield bindings.materialize(name);
|
|
130
|
+
}
|
|
118
131
|
yield stmt.first.initialize();
|
|
119
132
|
yield stmt.first.run();
|
|
120
133
|
yield stmt.first.finish();
|
|
@@ -149,6 +162,19 @@ class Runner {
|
|
|
149
162
|
this.bindParameters(child);
|
|
150
163
|
}
|
|
151
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Recursively walks the AST to collect the names of all
|
|
167
|
+
* `BindingReference`s. Used to refresh stale refreshable
|
|
168
|
+
* bindings before statement execution begins.
|
|
169
|
+
*/
|
|
170
|
+
collectBindingNames(node, names) {
|
|
171
|
+
if (node instanceof binding_reference_1.default) {
|
|
172
|
+
names.add(node.name);
|
|
173
|
+
}
|
|
174
|
+
for (const child of node.getChildren()) {
|
|
175
|
+
this.collectBindingNames(child, names);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
152
178
|
/**
|
|
153
179
|
* Gets the results from the executed statement.
|
|
154
180
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/compute/runner.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/compute/runner.ts"],"names":[],"mappings":"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"}
|