Skip to content

Commit b2014af

Browse files
authored
Adds support for runtime= (#481)
1 parent dfb31dd commit b2014af

File tree

7 files changed

+120
-2
lines changed

7 files changed

+120
-2
lines changed

Neo4jClient.Tests/Cypher/CypherFluentQueryPlannerTests.cs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,68 @@ public void ThrowsInvalidOperationException_WhenNeo4jVersionIsLessThan22()
5454
});
5555
}
5656
}
57+
58+
public class CypherFluentQueryRuntimeTests : IClassFixture<CultureInfoSetupFixture>
59+
{
60+
//Tests:
61+
// 2 - must be first in the list
62+
63+
[Fact]
64+
public void MustBeFirst()
65+
{
66+
var client = Substitute.For<IRawGraphClient>();
67+
client.CypherCapabilities.Returns(CypherCapabilities.Cypher35);
68+
69+
Assert.Throws<InvalidOperationException>(() =>
70+
{
71+
var _ = new CypherFluentQuery(client)
72+
.Match("(n)")
73+
.Runtime("Free")
74+
.Query;
75+
});
76+
}
77+
78+
[Fact]
79+
public void TestRuntimeWithFreeTextConstruction()
80+
{
81+
var client = Substitute.For<IRawGraphClient>();
82+
client.CypherCapabilities.Returns(CypherCapabilities.Cypher35);
83+
84+
var query = new CypherFluentQuery(client)
85+
.Runtime("Free")
86+
.Query;
87+
88+
Assert.Equal("CYPHER runtime=Free", query.QueryText);
89+
}
90+
91+
[Theory]
92+
[InlineData(CypherRuntime.Slotted, "slotted")]
93+
[InlineData(CypherRuntime.Pipelined, "pipelined")]
94+
[InlineData(CypherRuntime.Parallel, "parallel")]
95+
public void TestPlannerWithCypherPlannerVariant(CypherRuntime input, string expected)
96+
{
97+
var client = Substitute.For<IRawGraphClient>();
98+
client.CypherCapabilities.Returns(CypherCapabilities.Cypher35);
99+
100+
var query = new CypherFluentQuery(client)
101+
.Runtime(input)
102+
.Query;
103+
104+
Assert.Equal($"CYPHER runtime={expected}", query.QueryText);
105+
}
106+
107+
[Fact]
108+
public void ThrowsInvalidOperationException_WhenNeo4jVersionIsLessThan35()
109+
{
110+
var client = Substitute.For<IRawGraphClient>();
111+
client.CypherCapabilities.Returns(CypherCapabilities.Cypher30);
112+
113+
Assert.Throws<InvalidOperationException>(() =>
114+
{
115+
var _ = new CypherFluentQuery(client)
116+
.Runtime("Free")
117+
.Query;
118+
});
119+
}
120+
}
57121
}

Neo4jClient/BoltGraphClient.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,8 @@ public async Task ConnectAsync(NeoServerConfiguration configuration = null)
295295

296296
if (ServerVersion >= new Version(3, 0))
297297
CypherCapabilities = CypherCapabilities.Cypher30;
298+
if (ServerVersion >= new Version(3, 5))
299+
CypherCapabilities = CypherCapabilities.Cypher35;
298300
if(ServerVersion >= new Version(4,0))
299301
CypherCapabilities = CypherCapabilities.Cypher40;
300302
if(ServerVersion >= new Version(4,4))

Neo4jClient/Cypher/CypherCapabilities.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ public CypherCapabilities(CypherCapabilities cypherCapabilities)
3535
public static readonly CypherCapabilities Cypher226 = new CypherCapabilities(Cypher22) { AutoRollsBackOnError = true };
3636
public static readonly CypherCapabilities Cypher23 = new CypherCapabilities(Cypher226) {SupportsStartsWith = true};
3737
public static readonly CypherCapabilities Cypher30 = new CypherCapabilities(Cypher23) { SupportsStoredProcedures = true, SupportsHasFunction = false };
38-
public static readonly CypherCapabilities Cypher40 = new CypherCapabilities(Cypher30) { SupportsMultipleTenancy = true, SupportsShow = true };
38+
public static readonly CypherCapabilities Cypher35 = new CypherCapabilities(Cypher30) { SupportsRuntime = true };
39+
public static readonly CypherCapabilities Cypher40 = new CypherCapabilities(Cypher35) { SupportsMultipleTenancy = true, SupportsShow = true };
3940
public static readonly CypherCapabilities Cypher44 = new CypherCapabilities(Cypher40) { SupportsStoredProceduresWithTransactionalBatching = true };
40-
41+
4142
public static readonly CypherCapabilities Default = Cypher20;
4243

4344
/// <summary>
@@ -50,6 +51,11 @@ public CypherCapabilities(CypherCapabilities cypherCapabilities)
5051
public bool SupportsNullComparisonsWithIsOperator { get; set; }
5152
public bool SupportsStartsWith { get; set; }
5253
public bool SupportsStoredProceduresWithTransactionalBatching { get; set; }
54+
55+
/// <summary>
56+
/// Runtime is available to be set in 3.5 onwards.
57+
/// </summary>
58+
public bool SupportsRuntime { get; set; }
5359

5460
/// <summary>
5561
/// Cypher 3.0 provides support for Stored Procedures via the CALL keyword.

Neo4jClient/Cypher/CypherFluentQuery.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,33 @@ public ICypherFluentQuery ParserVersion(int major, int minor)
505505
return ParserVersion(new Version(major, minor));
506506
}
507507

508+
public ICypherFluentQuery Runtime(string runtime)
509+
{
510+
if(!Client.CypherCapabilities.SupportsRuntime)
511+
throw new InvalidOperationException("'runtime=' not supported in Neo4j versions older than 3.5");
512+
513+
if (!string.IsNullOrWhiteSpace(this.Query.QueryText))
514+
throw new InvalidOperationException("Runtime needs to be defined first.");
515+
516+
return Mutate(w => w.AppendClause($"CYPHER runtime={runtime}"));
517+
}
518+
519+
public ICypherFluentQuery Runtime(CypherRuntime runtime)
520+
{
521+
switch (runtime)
522+
{
523+
case CypherRuntime.Slotted:
524+
return Runtime("slotted");
525+
case CypherRuntime.Pipelined:
526+
return Runtime("pipelined");
527+
case CypherRuntime.Parallel:
528+
return Runtime("parallel");
529+
default:
530+
throw new ArgumentOutOfRangeException(nameof(runtime), runtime, null);
531+
}
532+
533+
}
534+
508535
public ICypherFluentQuery Planner(string planner)
509536
{
510537
if(!Client.CypherCapabilities.SupportsPlanner)

Neo4jClient/Cypher/CypherRuntime.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace Neo4jClient.Cypher
2+
{
3+
public enum CypherRuntime
4+
{
5+
/// <summary>The default for the Community Edition of Neo4j</summary>
6+
Slotted,
7+
/// <summary>The default for the Enterprise Edition of Neo4j</summary>
8+
Pipelined,
9+
/// <summary>Allows for multi-threaded execution of queries.</summary>
10+
/// <remarks>This does not always result in increased performance.</remarks>
11+
Parallel,
12+
}
13+
}

Neo4jClient/Cypher/ICypherFluentQuery.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ public partial interface ICypherFluentQuery
4949

5050
ICypherFluentQuery Planner(string planner);
5151
ICypherFluentQuery Planner(CypherPlanner planner);
52+
53+
ICypherFluentQuery Runtime(string runtime);
54+
ICypherFluentQuery Runtime(CypherRuntime runtime);
5255

5356
ICypherFluentQuery Match(params string[] matchText);
5457
ICypherFluentQuery UsingIndex(string index);

Neo4jClient/GraphClient.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ void StopTimerAndNotifyCompleted()
122122
if (version >= new Version(3, 0))
123123
CypherCapabilities = CypherCapabilities.Cypher30;
124124

125+
if (version >= new Version(3, 5))
126+
CypherCapabilities = CypherCapabilities.Cypher35;
127+
125128
if (version >= new Version(4, 0))
126129
CypherCapabilities = CypherCapabilities.Cypher40;
127130
if(ServerVersion >= new Version(4,4))

0 commit comments

Comments
 (0)