Skip to content

Commit f17f316

Browse files
authored
Merge pull request #585 from neo4j/list-comprehension-in
Breaking changes in ListComprehension
2 parents f0a27cd + 79d5abf commit f17f316

File tree

7 files changed

+64
-28
lines changed

7 files changed

+64
-28
lines changed

.changeset/bright-meals-arrive.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@neo4j/cypher-builder": major
3+
---
4+
5+
ListComprehension `.in` method no longer throws if called twice. It will instead override the expression

.changeset/clean-items-greet.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
"@neo4j/cypher-builder": major
3+
---
4+
5+
Remove second parameter of `ListComprehension` in favor of `.in`
6+
7+
_Before_
8+
9+
```js
10+
new Cypher.ListComprehension(variable, new Cypher.Literal([1, 2]));
11+
```
12+
13+
_After_
14+
15+
```js
16+
new Cypher.ListComprehension(variable).in(new Cypher.Literal([1, 2]));
17+
```
18+
19+
In both cases, the same comprehension will be generated:
20+
21+
```cypher
22+
[var0 IN [1, 2]]
23+
```

src/expressions/list/ListComprehension.test.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ describe("List comprehension", () => {
2525
const variable = new Cypher.Variable();
2626
const exprVariable = new Cypher.Param([1, 2, 5]);
2727

28-
const listComprehension = new Cypher.ListComprehension(variable, exprVariable);
28+
const listComprehension = new Cypher.ListComprehension(variable).in(exprVariable);
2929

3030
const queryResult = new TestClause(listComprehension).build();
3131

@@ -47,7 +47,7 @@ describe("List comprehension", () => {
4747
const exprVariable = new Cypher.Param([1, 2, 5]);
4848
const andExpr = Cypher.eq(variable, new Cypher.Param(5));
4949

50-
const listComprehension = new Cypher.ListComprehension(variable, exprVariable).where(andExpr);
50+
const listComprehension = new Cypher.ListComprehension(variable).in(exprVariable).where(andExpr);
5151

5252
const queryResult = new TestClause(listComprehension).build();
5353

@@ -91,16 +91,27 @@ describe("List comprehension", () => {
9191
`);
9292
});
9393

94-
it("Fails to set a expression twice", () => {
94+
test("Overrides if a expression is set twice", () => {
9595
const variable = new Cypher.Variable();
9696
const exprVariable = new Cypher.Param([1, 2, 5]);
97+
const exprVariable2 = new Cypher.Param([1, 3]);
9798

98-
expect(() => {
99-
new Cypher.ListComprehension(variable, exprVariable).in(exprVariable);
100-
}).toThrow("Cannot set 2 lists in list comprehension IN");
99+
const listComprehension = new Cypher.ListComprehension(variable).in(exprVariable).in(exprVariable2);
100+
101+
const queryResult = new TestClause(listComprehension).build();
102+
103+
expect(queryResult.cypher).toMatchInlineSnapshot(`"[var0 IN $param0]"`);
104+
expect(queryResult.params).toMatchInlineSnapshot(`
105+
{
106+
"param0": [
107+
1,
108+
3,
109+
],
110+
}
111+
`);
101112
});
102113

103-
it("Fails to build if no expression is set", () => {
114+
test("Fails to build if no expression is set", () => {
104115
const variable = new Cypher.Variable();
105116

106117
const listComprehension = new Cypher.ListComprehension(variable);

src/expressions/list/ListComprehension.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,13 @@ export class ListComprehension extends CypherASTNode {
3838
private listExpr: Expr | undefined;
3939
private mapExpr: Expr | undefined; // Expression for list mapping
4040

41-
constructor(variable: Variable, listExpr?: Expr) {
41+
constructor(variable: Variable) {
4242
super();
4343
this.variable = variable;
44-
this.listExpr = listExpr;
4544
}
4645

46+
/** Sets the list expression to be used for the comprehension. If called twice, the expression will be overriden */
4747
public in(listExpr: Expr): this {
48-
if (this.listExpr) throw new Error("Cannot set 2 lists in list comprehension IN");
4948
this.listExpr = listExpr;
5049
return this;
5150
}

src/pattern/Pattern.test.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,7 @@ describe("Patterns", () => {
283283
const a = new Cypher.Node();
284284
const rel = new Cypher.Variable();
285285

286-
const query = new TestClause(
287-
new Cypher.Pattern(a as Cypher.Node | undefined).related(rel).to(a as Cypher.Node | undefined)
288-
);
286+
const query = new TestClause(new Cypher.Pattern(a).related(rel).to(a));
289287
const queryResult = query.build();
290288
expect(queryResult.cypher).toMatchInlineSnapshot(`"(this0)-[var1]->(this0)"`);
291289

@@ -429,7 +427,7 @@ describe("Patterns", () => {
429427
});
430428

431429
describe("Where predicate", () => {
432-
it("Node pattern with where predicate", () => {
430+
test("Node pattern with where predicate", () => {
433431
const node = new Cypher.Node();
434432

435433
const pattern = new Cypher.Pattern(node, { labels: ["TestLabel"] }).where(
@@ -439,7 +437,7 @@ describe("Patterns", () => {
439437
expect(queryResult.cypher).toMatchInlineSnapshot(`"(this0:TestLabel WHERE this0.name = \\"Keanu\\")"`);
440438
});
441439

442-
it("Node pattern with where predicate and properties", () => {
440+
test("Node pattern with where predicate and properties", () => {
443441
const node = new Cypher.Node();
444442

445443
const pattern = new Cypher.Pattern(node, {
@@ -457,7 +455,7 @@ describe("Patterns", () => {
457455
);
458456
});
459457

460-
it("Node pattern with where predicate in target node", () => {
458+
test("Node pattern with where predicate in target node", () => {
461459
const node = new Cypher.Node();
462460

463461
const pattern = new Cypher.Pattern(node, { labels: ["TestLabel"] })
@@ -470,7 +468,7 @@ describe("Patterns", () => {
470468
);
471469
});
472470

473-
it("Relationship pattern with where predicate", () => {
471+
test("Relationship pattern with where predicate", () => {
474472
const node = new Cypher.Node();
475473
const relationship = new Cypher.Relationship();
476474

@@ -484,7 +482,7 @@ describe("Patterns", () => {
484482
);
485483
});
486484

487-
it("Relationship pattern with where predicate and properties", () => {
485+
test("Relationship pattern with where predicate and properties", () => {
488486
const node = new Cypher.Node();
489487
const relationship = new Cypher.Relationship();
490488

src/procedures/CypherProcedure.test.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ describe("Procedures", () => {
134134
});
135135

136136
describe("Procedure with Yield and nested clauses", () => {
137-
it("Procedure with Where", () => {
137+
test("Procedure with Where", () => {
138138
const procedure = new Cypher.Procedure("custom-procedure").yield("test");
139139

140140
procedure.where(Cypher.true).and(Cypher.false).return("*");
@@ -148,7 +148,7 @@ RETURN *"
148148
expect(params).toMatchInlineSnapshot(`{}`);
149149
});
150150

151-
it("Procedure with Delete", () => {
151+
test("Procedure with Delete", () => {
152152
const procedure = new Cypher.Procedure("custom-procedure").yield("test");
153153

154154
procedure.delete(new Cypher.Node());
@@ -161,7 +161,7 @@ DELETE this0"
161161
expect(params).toMatchInlineSnapshot(`{}`);
162162
});
163163

164-
it("Procedure with Detach Delete", () => {
164+
test("Procedure with Detach Delete", () => {
165165
const procedure = new Cypher.Procedure("custom-procedure").yield("test");
166166

167167
procedure.detachDelete(new Cypher.Node());
@@ -174,7 +174,7 @@ DETACH DELETE this0"
174174
expect(params).toMatchInlineSnapshot(`{}`);
175175
});
176176

177-
it("Procedure with Remove", () => {
177+
test("Procedure with Remove", () => {
178178
const procedure = new Cypher.Procedure("custom-procedure").yield("test");
179179

180180
procedure.remove(new Cypher.Node().property("test"));
@@ -187,7 +187,7 @@ REMOVE this0.test"
187187
expect(params).toMatchInlineSnapshot(`{}`);
188188
});
189189

190-
it("Procedure with Set", () => {
190+
test("Procedure with Set", () => {
191191
const procedure = new Cypher.Procedure("custom-procedure").yield("test");
192192

193193
procedure.set([new Cypher.Variable().property("test"), new Cypher.Literal("hello")]);
@@ -201,7 +201,7 @@ SET
201201
expect(params).toMatchInlineSnapshot(`{}`);
202202
});
203203

204-
it("Procedure with Unwind", () => {
204+
test("Procedure with Unwind", () => {
205205
const yieldVar = new Cypher.Variable();
206206
const procedure = new Cypher.Procedure("custom-procedure").yield(["test", yieldVar]);
207207

@@ -215,7 +215,7 @@ UNWIND var0 AS var1"
215215
expect(params).toMatchInlineSnapshot(`{}`);
216216
});
217217

218-
it("Procedure with Merge", () => {
218+
test("Procedure with Merge", () => {
219219
const procedure = new Cypher.Procedure("custom-procedure").yield("test");
220220

221221
procedure.merge(new Cypher.Pattern(new Cypher.Node()));
@@ -228,7 +228,7 @@ MERGE (this0)"
228228
expect(params).toMatchInlineSnapshot(`{}`);
229229
});
230230

231-
it("Procedure with Create", () => {
231+
test("Procedure with Create", () => {
232232
const procedure = new Cypher.Procedure("custom-procedure").yield("test");
233233

234234
procedure.create(new Cypher.Pattern(new Cypher.Node()));
@@ -241,7 +241,7 @@ CREATE (this0)"
241241
expect(params).toMatchInlineSnapshot(`{}`);
242242
});
243243

244-
it("Procedure with Order by", () => {
244+
test("Procedure with Order by", () => {
245245
const testVar = new Cypher.NamedVariable("test");
246246
const procedure = new Cypher.Procedure("custom-procedure").yield("test").orderBy(testVar).skip(1).limit(10);
247247

src/utils/utils.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ describe("CypherBuilder Utils", () => {
8383
});
8484
});
8585

86-
it("toCypherParams", () => {
86+
test("toCypherParams", () => {
8787
const cypherParams = Cypher.utils.toCypherParams({
8888
param1: "my param",
8989
param2: 5,

0 commit comments

Comments
 (0)