flowquery 1.0.33 → 1.0.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/flowquery.min.js +1 -1
- package/dist/graph/database.d.ts +1 -0
- package/dist/graph/database.d.ts.map +1 -1
- package/dist/graph/database.js +43 -6
- package/dist/graph/database.js.map +1 -1
- package/dist/graph/relationship.d.ts +3 -1
- package/dist/graph/relationship.d.ts.map +1 -1
- package/dist/graph/relationship.js +12 -4
- package/dist/graph/relationship.js.map +1 -1
- package/dist/graph/relationship_data.js +1 -1
- package/dist/graph/relationship_data.js.map +1 -1
- package/dist/graph/relationship_match_collector.d.ts.map +1 -1
- package/dist/graph/relationship_match_collector.js +6 -3
- package/dist/graph/relationship_match_collector.js.map +1 -1
- package/dist/graph/relationship_reference.js +1 -1
- package/dist/graph/relationship_reference.js.map +1 -1
- package/dist/parsing/functions/function_factory.d.ts +3 -0
- package/dist/parsing/functions/function_factory.d.ts.map +1 -1
- package/dist/parsing/functions/function_factory.js +3 -0
- package/dist/parsing/functions/function_factory.js.map +1 -1
- package/dist/parsing/functions/predicate_sum.d.ts.map +1 -1
- package/dist/parsing/functions/predicate_sum.js +13 -10
- package/dist/parsing/functions/predicate_sum.js.map +1 -1
- package/dist/parsing/functions/schema.d.ts +5 -2
- package/dist/parsing/functions/schema.d.ts.map +1 -1
- package/dist/parsing/functions/schema.js +7 -4
- package/dist/parsing/functions/schema.js.map +1 -1
- package/dist/parsing/functions/to_lower.d.ts +7 -0
- package/dist/parsing/functions/to_lower.d.ts.map +1 -0
- package/dist/parsing/functions/to_lower.js +37 -0
- package/dist/parsing/functions/to_lower.js.map +1 -0
- package/dist/parsing/functions/to_string.d.ts +7 -0
- package/dist/parsing/functions/to_string.d.ts.map +1 -0
- package/dist/parsing/functions/to_string.js +44 -0
- package/dist/parsing/functions/to_string.js.map +1 -0
- package/dist/parsing/functions/trim.d.ts +7 -0
- package/dist/parsing/functions/trim.d.ts.map +1 -0
- package/dist/parsing/functions/trim.js +37 -0
- package/dist/parsing/functions/trim.js.map +1 -0
- package/dist/parsing/operations/group_by.d.ts.map +1 -1
- package/dist/parsing/operations/group_by.js +4 -2
- package/dist/parsing/operations/group_by.js.map +1 -1
- package/dist/parsing/parser.d.ts.map +1 -1
- package/dist/parsing/parser.js +15 -2
- package/dist/parsing/parser.js.map +1 -1
- package/docs/flowquery.min.js +1 -1
- package/flowquery-py/pyproject.toml +1 -1
- package/flowquery-py/src/graph/database.py +44 -11
- package/flowquery-py/src/graph/relationship.py +11 -3
- package/flowquery-py/src/graph/relationship_data.py +2 -1
- package/flowquery-py/src/graph/relationship_match_collector.py +7 -1
- package/flowquery-py/src/graph/relationship_reference.py +2 -2
- package/flowquery-py/src/parsing/functions/__init__.py +6 -0
- package/flowquery-py/src/parsing/functions/predicate_sum.py +3 -6
- package/flowquery-py/src/parsing/functions/schema.py +9 -5
- package/flowquery-py/src/parsing/functions/to_lower.py +35 -0
- package/flowquery-py/src/parsing/functions/to_string.py +41 -0
- package/flowquery-py/src/parsing/functions/trim.py +35 -0
- package/flowquery-py/src/parsing/operations/group_by.py +2 -0
- package/flowquery-py/src/parsing/parser.py +12 -2
- package/flowquery-py/tests/compute/test_runner.py +294 -4
- package/flowquery-vscode/flowQueryEngine/flowquery.min.js +1 -1
- package/package.json +1 -1
- package/src/graph/database.ts +42 -4
- package/src/graph/relationship.ts +12 -4
- package/src/graph/relationship_data.ts +1 -1
- package/src/graph/relationship_match_collector.ts +6 -2
- package/src/graph/relationship_reference.ts +1 -1
- package/src/parsing/functions/function_factory.ts +3 -0
- package/src/parsing/functions/predicate_sum.ts +17 -12
- package/src/parsing/functions/schema.ts +7 -4
- package/src/parsing/functions/to_lower.ts +25 -0
- package/src/parsing/functions/to_string.ts +32 -0
- package/src/parsing/functions/trim.ts +25 -0
- package/src/parsing/operations/group_by.ts +4 -1
- package/src/parsing/parser.ts +15 -2
- package/tests/compute/runner.test.ts +319 -3
- package/tests/parsing/parser.test.ts +37 -0
package/package.json
CHANGED
package/src/graph/database.ts
CHANGED
|
@@ -34,20 +34,34 @@ class Database {
|
|
|
34
34
|
}
|
|
35
35
|
const physical = new PhysicalRelationship(null, relationship.type);
|
|
36
36
|
physical.statement = statement;
|
|
37
|
+
physical.source = relationship.source;
|
|
38
|
+
physical.target = relationship.target;
|
|
37
39
|
Database.relationships.set(relationship.type, physical);
|
|
38
40
|
}
|
|
39
41
|
public getRelationship(relationship: Relationship): PhysicalRelationship | null {
|
|
40
42
|
return Database.relationships.get(relationship.type!) || null;
|
|
41
43
|
}
|
|
44
|
+
public getRelationships(relationship: Relationship): PhysicalRelationship[] {
|
|
45
|
+
const result: PhysicalRelationship[] = [];
|
|
46
|
+
for (const type of relationship.types) {
|
|
47
|
+
const physical = Database.relationships.get(type);
|
|
48
|
+
if (physical) {
|
|
49
|
+
result.push(physical);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
42
54
|
public async schema(): Promise<Record<string, any>[]> {
|
|
43
55
|
const result: Record<string, any>[] = [];
|
|
44
56
|
|
|
45
57
|
for (const [label, physical] of Database.nodes) {
|
|
46
58
|
const records = await physical.data();
|
|
47
|
-
const entry: Record<string, any> = { kind: "
|
|
59
|
+
const entry: Record<string, any> = { kind: "Node", label };
|
|
48
60
|
if (records.length > 0) {
|
|
49
61
|
const { id, ...sample } = records[0];
|
|
50
|
-
|
|
62
|
+
const properties = Object.keys(sample);
|
|
63
|
+
if (properties.length > 0) {
|
|
64
|
+
entry.properties = properties;
|
|
51
65
|
entry.sample = sample;
|
|
52
66
|
}
|
|
53
67
|
}
|
|
@@ -56,10 +70,17 @@ class Database {
|
|
|
56
70
|
|
|
57
71
|
for (const [type, physical] of Database.relationships) {
|
|
58
72
|
const records = await physical.data();
|
|
59
|
-
const entry: Record<string, any> = {
|
|
73
|
+
const entry: Record<string, any> = {
|
|
74
|
+
kind: "Relationship",
|
|
75
|
+
type,
|
|
76
|
+
from_label: physical.source?.label || null,
|
|
77
|
+
to_label: physical.target?.label || null,
|
|
78
|
+
};
|
|
60
79
|
if (records.length > 0) {
|
|
61
80
|
const { left_id, right_id, ...sample } = records[0];
|
|
62
|
-
|
|
81
|
+
const properties = Object.keys(sample);
|
|
82
|
+
if (properties.length > 0) {
|
|
83
|
+
entry.properties = properties;
|
|
63
84
|
entry.sample = sample;
|
|
64
85
|
}
|
|
65
86
|
}
|
|
@@ -78,6 +99,23 @@ class Database {
|
|
|
78
99
|
const data = await node.data();
|
|
79
100
|
return new NodeData(data as NodeRecord[]);
|
|
80
101
|
} else if (element instanceof Relationship) {
|
|
102
|
+
if (element.types.length > 1) {
|
|
103
|
+
const physicals = this.getRelationships(element);
|
|
104
|
+
if (physicals.length === 0) {
|
|
105
|
+
throw new Error(
|
|
106
|
+
`No physical relationships found for types ${element.types.join(", ")}`
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
const allRecords: RelationshipRecord[] = [];
|
|
110
|
+
for (let i = 0; i < physicals.length; i++) {
|
|
111
|
+
const records = (await physicals[i].data()) as RelationshipRecord[];
|
|
112
|
+
const typeName = element.types[i];
|
|
113
|
+
for (const record of records) {
|
|
114
|
+
allRecords.push({ ...record, _type: typeName });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return new RelationshipData(allRecords);
|
|
118
|
+
}
|
|
81
119
|
const relationship = this.getRelationship(element);
|
|
82
120
|
if (relationship === null) {
|
|
83
121
|
throw new Error(`Physical relationship not found for type ${element.type}`);
|
|
@@ -9,7 +9,7 @@ import RelationshipMatchCollector, {
|
|
|
9
9
|
|
|
10
10
|
class Relationship extends ASTNode {
|
|
11
11
|
protected _identifier: string | null = null;
|
|
12
|
-
protected
|
|
12
|
+
protected _types: string[] = [];
|
|
13
13
|
protected _properties: Map<string, Expression> = new Map();
|
|
14
14
|
protected _hops: Hops = new Hops();
|
|
15
15
|
|
|
@@ -25,7 +25,9 @@ class Relationship extends ASTNode {
|
|
|
25
25
|
constructor(identifier: string | null = null, type: string | null = null) {
|
|
26
26
|
super();
|
|
27
27
|
this._identifier = identifier;
|
|
28
|
-
|
|
28
|
+
if (type !== null) {
|
|
29
|
+
this._types = [type];
|
|
30
|
+
}
|
|
29
31
|
}
|
|
30
32
|
public set identifier(identifier: string) {
|
|
31
33
|
this._identifier = identifier;
|
|
@@ -34,10 +36,16 @@ class Relationship extends ASTNode {
|
|
|
34
36
|
return this._identifier;
|
|
35
37
|
}
|
|
36
38
|
public set type(type: string) {
|
|
37
|
-
this.
|
|
39
|
+
this._types = [type];
|
|
38
40
|
}
|
|
39
41
|
public get type(): string | null {
|
|
40
|
-
return this.
|
|
42
|
+
return this._types.length > 0 ? this._types[0] : null;
|
|
43
|
+
}
|
|
44
|
+
public set types(types: string[]) {
|
|
45
|
+
this._types = types;
|
|
46
|
+
}
|
|
47
|
+
public get types(): string[] {
|
|
48
|
+
return this._types;
|
|
41
49
|
}
|
|
42
50
|
public get properties(): Map<string, Expression> {
|
|
43
51
|
return this._properties;
|
|
@@ -18,7 +18,7 @@ class RelationshipData extends Data {
|
|
|
18
18
|
public properties(): Record<string, any> | null {
|
|
19
19
|
const current = this.current();
|
|
20
20
|
if (current) {
|
|
21
|
-
const { left_id, right_id, ...props } = current;
|
|
21
|
+
const { left_id, right_id, _type, ...props } = current;
|
|
22
22
|
return props;
|
|
23
23
|
}
|
|
24
24
|
return null;
|
|
@@ -12,11 +12,15 @@ class RelationshipMatchCollector {
|
|
|
12
12
|
private _nodeIds: Array<string> = [];
|
|
13
13
|
|
|
14
14
|
public push(relationship: Relationship, traversalId: string): RelationshipMatchRecord {
|
|
15
|
+
const data = relationship.getData();
|
|
16
|
+
const currentRecord = data?.current();
|
|
17
|
+
const actualType =
|
|
18
|
+
currentRecord && "_type" in currentRecord ? currentRecord["_type"] : relationship.type!;
|
|
15
19
|
const match: RelationshipMatchRecord = {
|
|
16
|
-
type:
|
|
20
|
+
type: actualType,
|
|
17
21
|
startNode: relationship.source?.value() || {},
|
|
18
22
|
endNode: null,
|
|
19
|
-
properties:
|
|
23
|
+
properties: data?.properties() as Record<string, any>,
|
|
20
24
|
};
|
|
21
25
|
this._matches.push(match);
|
|
22
26
|
this._nodeIds.push(traversalId);
|
|
@@ -6,7 +6,7 @@ class RelationshipReference extends Relationship {
|
|
|
6
6
|
constructor(base: Relationship, reference: Relationship) {
|
|
7
7
|
super();
|
|
8
8
|
this._identifier = base.identifier;
|
|
9
|
-
this.
|
|
9
|
+
this._types = base.types;
|
|
10
10
|
this._hops = base.hops!;
|
|
11
11
|
this._source = base.source;
|
|
12
12
|
this._target = base.target;
|
|
@@ -27,6 +27,9 @@ import "./stringify";
|
|
|
27
27
|
// Import built-in functions to ensure their @FunctionDef decorators run
|
|
28
28
|
import "./sum";
|
|
29
29
|
import "./to_json";
|
|
30
|
+
import "./to_lower";
|
|
31
|
+
import "./to_string";
|
|
32
|
+
import "./trim";
|
|
30
33
|
import "./type";
|
|
31
34
|
|
|
32
35
|
// Re-export AsyncDataProvider for backwards compatibility
|
|
@@ -1,17 +1,26 @@
|
|
|
1
|
-
import PredicateFunction from "./predicate_function";
|
|
2
1
|
import { FunctionDef } from "./function_metadata";
|
|
2
|
+
import PredicateFunction from "./predicate_function";
|
|
3
3
|
|
|
4
4
|
@FunctionDef({
|
|
5
|
-
description:
|
|
5
|
+
description:
|
|
6
|
+
"Calculates the sum of values in an array with optional filtering. Uses list comprehension syntax: sum(variable IN array [WHERE condition] | expression)",
|
|
6
7
|
category: "predicate",
|
|
7
8
|
parameters: [
|
|
8
9
|
{ name: "variable", description: "Variable name to bind each element", type: "string" },
|
|
9
10
|
{ name: "array", description: "Array to iterate over", type: "array" },
|
|
10
11
|
{ name: "expression", description: "Expression to sum for each element", type: "any" },
|
|
11
|
-
{
|
|
12
|
+
{
|
|
13
|
+
name: "where",
|
|
14
|
+
description: "Optional filter condition",
|
|
15
|
+
type: "boolean",
|
|
16
|
+
required: false,
|
|
17
|
+
},
|
|
12
18
|
],
|
|
13
19
|
output: { description: "Sum of the evaluated expressions", type: "number", example: 6 },
|
|
14
|
-
examples: [
|
|
20
|
+
examples: [
|
|
21
|
+
"WITH [1, 2, 3] AS nums RETURN sum(n IN nums | n)",
|
|
22
|
+
"WITH [1, 2, 3, 4] AS nums RETURN sum(n IN nums WHERE n > 1 | n * 2)",
|
|
23
|
+
],
|
|
15
24
|
})
|
|
16
25
|
class PredicateSum extends PredicateFunction {
|
|
17
26
|
constructor() {
|
|
@@ -24,19 +33,15 @@ class PredicateSum extends PredicateFunction {
|
|
|
24
33
|
if (array === null || !Array.isArray(array)) {
|
|
25
34
|
throw new Error("Invalid array for sum function");
|
|
26
35
|
}
|
|
27
|
-
let _sum:
|
|
28
|
-
for(let i = 0; i < array.length; i++) {
|
|
36
|
+
let _sum: number = 0;
|
|
37
|
+
for (let i = 0; i < array.length; i++) {
|
|
29
38
|
this._valueHolder.holder = array[i];
|
|
30
39
|
if (this.where === null || this.where.value()) {
|
|
31
|
-
|
|
32
|
-
_sum = this._return.value();
|
|
33
|
-
} else {
|
|
34
|
-
_sum += this._return.value();
|
|
35
|
-
}
|
|
40
|
+
_sum += this._return.value();
|
|
36
41
|
}
|
|
37
42
|
}
|
|
38
43
|
return _sum;
|
|
39
44
|
}
|
|
40
45
|
}
|
|
41
46
|
|
|
42
|
-
export default PredicateSum;
|
|
47
|
+
export default PredicateSum;
|
|
@@ -5,8 +5,11 @@ import { FunctionDef } from "./function_metadata";
|
|
|
5
5
|
/**
|
|
6
6
|
* Built-in function that returns the graph schema of the database.
|
|
7
7
|
*
|
|
8
|
-
* Lists all nodes and relationships with their labels/types
|
|
9
|
-
* of their data (excluding id from nodes, left_id and right_id from relationships).
|
|
8
|
+
* Lists all nodes and relationships with their labels/types, properties,
|
|
9
|
+
* and a sample of their data (excluding id from nodes, left_id and right_id from relationships).
|
|
10
|
+
*
|
|
11
|
+
* Nodes: {label, properties, sample}
|
|
12
|
+
* Relationships: {type, from_label, to_label, properties, sample}
|
|
10
13
|
*
|
|
11
14
|
* @example
|
|
12
15
|
* ```
|
|
@@ -15,11 +18,11 @@ import { FunctionDef } from "./function_metadata";
|
|
|
15
18
|
*/
|
|
16
19
|
@FunctionDef({
|
|
17
20
|
description:
|
|
18
|
-
"Returns the graph schema listing all nodes and relationships with a sample of their data.",
|
|
21
|
+
"Returns the graph schema listing all nodes and relationships with their properties and a sample of their data.",
|
|
19
22
|
category: "async",
|
|
20
23
|
parameters: [],
|
|
21
24
|
output: {
|
|
22
|
-
description: "Schema entry with
|
|
25
|
+
description: "Schema entry with label/type, properties, and optional sample data",
|
|
23
26
|
type: "object",
|
|
24
27
|
},
|
|
25
28
|
examples: ["LOAD FROM schema() AS s RETURN s"],
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import Function from "./function";
|
|
2
|
+
import { FunctionDef } from "./function_metadata";
|
|
3
|
+
|
|
4
|
+
@FunctionDef({
|
|
5
|
+
description: "Converts a string to lowercase",
|
|
6
|
+
category: "scalar",
|
|
7
|
+
parameters: [{ name: "text", description: "String to convert to lowercase", type: "string" }],
|
|
8
|
+
output: { description: "Lowercase string", type: "string", example: "hello world" },
|
|
9
|
+
examples: ["WITH 'Hello World' AS s RETURN toLower(s)", "WITH 'FOO' AS s RETURN toLower(s)"],
|
|
10
|
+
})
|
|
11
|
+
class ToLower extends Function {
|
|
12
|
+
constructor() {
|
|
13
|
+
super("tolower");
|
|
14
|
+
this._expectedParameterCount = 1;
|
|
15
|
+
}
|
|
16
|
+
public value(): any {
|
|
17
|
+
const val = this.getChildren()[0].value();
|
|
18
|
+
if (typeof val !== "string") {
|
|
19
|
+
throw new Error("Invalid argument for toLower function: expected a string");
|
|
20
|
+
}
|
|
21
|
+
return val.toLowerCase();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default ToLower;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import Function from "./function";
|
|
2
|
+
import { FunctionDef } from "./function_metadata";
|
|
3
|
+
|
|
4
|
+
@FunctionDef({
|
|
5
|
+
description: "Converts a value to its string representation",
|
|
6
|
+
category: "scalar",
|
|
7
|
+
parameters: [{ name: "value", description: "Value to convert to a string", type: "any" }],
|
|
8
|
+
output: { description: "String representation of the value", type: "string", example: "42" },
|
|
9
|
+
examples: [
|
|
10
|
+
"WITH 42 AS n RETURN toString(n)",
|
|
11
|
+
"WITH true AS b RETURN toString(b)",
|
|
12
|
+
"WITH [1, 2, 3] AS arr RETURN toString(arr)",
|
|
13
|
+
],
|
|
14
|
+
})
|
|
15
|
+
class ToString extends Function {
|
|
16
|
+
constructor() {
|
|
17
|
+
super("tostring");
|
|
18
|
+
this._expectedParameterCount = 1;
|
|
19
|
+
}
|
|
20
|
+
public value(): any {
|
|
21
|
+
const val = this.getChildren()[0].value();
|
|
22
|
+
if (val === null || val === undefined) {
|
|
23
|
+
return String(val);
|
|
24
|
+
}
|
|
25
|
+
if (typeof val === "object") {
|
|
26
|
+
return JSON.stringify(val);
|
|
27
|
+
}
|
|
28
|
+
return String(val);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default ToString;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import Function from "./function";
|
|
2
|
+
import { FunctionDef } from "./function_metadata";
|
|
3
|
+
|
|
4
|
+
@FunctionDef({
|
|
5
|
+
description: "Removes leading and trailing whitespace from a string",
|
|
6
|
+
category: "scalar",
|
|
7
|
+
parameters: [{ name: "text", description: "String to trim", type: "string" }],
|
|
8
|
+
output: { description: "Trimmed string", type: "string", example: "hello" },
|
|
9
|
+
examples: ["WITH ' hello ' AS s RETURN trim(s)", "WITH '\\tfoo\\n' AS s RETURN trim(s)"],
|
|
10
|
+
})
|
|
11
|
+
class Trim extends Function {
|
|
12
|
+
constructor() {
|
|
13
|
+
super("trim");
|
|
14
|
+
this._expectedParameterCount = 1;
|
|
15
|
+
}
|
|
16
|
+
public value(): any {
|
|
17
|
+
const val = this.getChildren()[0].value();
|
|
18
|
+
if (typeof val !== "string") {
|
|
19
|
+
throw new Error("Invalid argument for trim function: expected a string");
|
|
20
|
+
}
|
|
21
|
+
return val.trim();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default Trim;
|
|
@@ -106,7 +106,10 @@ class GroupBy extends Projection {
|
|
|
106
106
|
yield* this.generate_results(mapperIndex + 1, child);
|
|
107
107
|
}
|
|
108
108
|
} else {
|
|
109
|
-
node.elements
|
|
109
|
+
if (node.elements === null) {
|
|
110
|
+
node.elements = this.reducers.map((reducer) => reducer.element());
|
|
111
|
+
}
|
|
112
|
+
node.elements.forEach((element, reducerIndex) => {
|
|
110
113
|
this.reducers[reducerIndex].overridden = element.value;
|
|
111
114
|
});
|
|
112
115
|
const record: Record<string, any> = {};
|
package/src/parsing/parser.ts
CHANGED
|
@@ -420,6 +420,8 @@ class Parser extends BaseParser {
|
|
|
420
420
|
}
|
|
421
421
|
relationship = new Relationship();
|
|
422
422
|
relationship.type = type;
|
|
423
|
+
relationship.source = node;
|
|
424
|
+
relationship.target = target;
|
|
423
425
|
}
|
|
424
426
|
this.expectAndSkipWhitespaceAndComments();
|
|
425
427
|
if (!this.token.isAs()) {
|
|
@@ -673,8 +675,19 @@ class Parser extends BaseParser {
|
|
|
673
675
|
if (!this.token.isIdentifierOrKeyword()) {
|
|
674
676
|
throw new Error("Expected relationship type identifier");
|
|
675
677
|
}
|
|
676
|
-
const
|
|
678
|
+
const types: string[] = [this.token.value || ""];
|
|
677
679
|
this.setNextToken();
|
|
680
|
+
while (this.token.isPipe()) {
|
|
681
|
+
this.setNextToken();
|
|
682
|
+
if (this.token.isColon()) {
|
|
683
|
+
this.setNextToken();
|
|
684
|
+
}
|
|
685
|
+
if (!this.token.isIdentifierOrKeyword()) {
|
|
686
|
+
throw new Error("Expected relationship type identifier after '|'");
|
|
687
|
+
}
|
|
688
|
+
types.push(this.token.value || "");
|
|
689
|
+
this.setNextToken();
|
|
690
|
+
}
|
|
678
691
|
const hops: Hops | null = this.parseRelationshipHops();
|
|
679
692
|
const properties: Map<string, Expression> = new Map(this.parseProperties());
|
|
680
693
|
if (!this.token.isClosingBracket()) {
|
|
@@ -711,7 +724,7 @@ class Parser extends BaseParser {
|
|
|
711
724
|
if (hops !== null) {
|
|
712
725
|
relationship.hops = hops;
|
|
713
726
|
}
|
|
714
|
-
relationship.
|
|
727
|
+
relationship.types = types;
|
|
715
728
|
return relationship;
|
|
716
729
|
}
|
|
717
730
|
|