diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 61a65871e04..1833354e01a 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -89,6 +89,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima * Updated all default Gremlin Server configs to remove Groovy dependency from initialization. * Added script engine allowlist to Gremlin Server - the `scriptEngines` YAML configuration now restricts which engines can serve requests; `gremlin-lang` is always available. * Modified request parameters from `Map` to gremlin-lang compatible `String`. +* Renamed the request `bindings` field to `parameters` across the HTTP request body, GraphBinary, and GraphSON, standardizing terminology for query parameters. * Modified HTTP API to expect gremlin-lang strings for parameters and update all GLVs to send requests in new format. * Added string parameter parsing to `GremlinServer` to prevent traversal injection and excessive nesting depths. * Modified all GLVs to detect unsupported types in `GremlinLang` and throw consistent error for that case. diff --git a/docs/src/dev/io/graphson.asciidoc b/docs/src/dev/io/graphson.asciidoc index 7b3a872d9b0..d9a66071926 100644 --- a/docs/src/dev/io/graphson.asciidoc +++ b/docs/src/dev/io/graphson.asciidoc @@ -2751,7 +2751,7 @@ The following `RequestMessage` is an example of a simple sessionless request for "@value": 1000 }, "g": "g", - "bindings": { + "parameters": { "@type": "g:Map", "@value": [ "x", @@ -2772,7 +2772,7 @@ The following `RequestMessage` is an example of a simple sessionless request for "materializeProperties": "tokens", "timeoutMs": 1000, "g": "g", - "bindings": { + "parameters": { "x": 1 }, "language": "gremlin-groovy" diff --git a/docs/src/dev/provider/index.asciidoc b/docs/src/dev/provider/index.asciidoc index 1e2c7411090..7bffb865db9 100644 --- a/docs/src/dev/provider/index.asciidoc +++ b/docs/src/dev/provider/index.asciidoc @@ -1198,7 +1198,7 @@ Gremlin-Hints: { "gremlin": string, "timeoutMs": number, - "bindings": string, + "parameters": string, "g": string, "language" : string, "materializeProperties": string, @@ -1258,7 +1258,7 @@ the serializer specified by the `Content-Type` header. The following are the key |Key |Description |Value |Required |gremlin |The Gremlin query to execute. |String containing script |Yes |timeoutMs |The maximum time a query is allowed to execute in milliseconds. |Number between 0 and 2^31-1 |No -|bindings |A gremlin-lang string that contains a map used during query execution. Its usage depends on "language". For "gremlin-groovy", these are the variable bindings. For "gremlin-lang", these are the parameter bindings. |Object (Map) |No +|parameters |A gremlin-lang string that encodes a map of key/value pairs used during query execution. Its usage depends on "language". For "gremlin-groovy", these are applied as script variable bindings. For "gremlin-lang", these are the query parameters. |String containing a gremlin-lang map literal |No |g |The name of the graph traversal source to which the query applies. Default: "g" |String containing traversal source name |No |language |The name of the ScriptEngine to use to parse the gremlin query. Default: "gremlin-lang" |String containing ScriptEngine name |No |materializeProperties |Whether to include all properties for results. One of "tokens" or "all". |String |No @@ -1270,7 +1270,7 @@ the serializer specified by the `Content-Type` header. The following are the key When Gremlin Server receives that request, it will decode it given the "mime type", and execute it using the `ScriptEngine` specified by the `language` field. In this case, it will evaluate the script `g.V(x).out()` using the -`bindings` supplied in the `args` and stream back the results in HTTP chunks. When the chunks are combined, they will +`parameters` supplied in the `args` and stream back the results in HTTP chunks. When the chunks are combined, they will form a single `ResponseMessage`. The HTTP response containing the `ResponseMessage` has the following form: [source,text] diff --git a/docs/src/reference/gremlin-applications.asciidoc b/docs/src/reference/gremlin-applications.asciidoc index eaa9950b697..77e76e1f27b 100644 --- a/docs/src/reference/gremlin-applications.asciidoc +++ b/docs/src/reference/gremlin-applications.asciidoc @@ -682,7 +682,7 @@ list = g.V().has("person","name","marko").out("knows").toList() // script client, err := NewClient("http://localhost:8182/gremlin") resultSet, err := client.SubmitWithOptions("g.V().has('person','name',name).out('knows')", - new(RequestOptionsBuilder).AddBinding("name", "marko").Create()) + new(RequestOptionsBuilder).AddParameter("name", "marko").Create()) result, err := resultSet.All() // traversal @@ -805,21 +805,14 @@ returns: `POST` is the only supported method for this endpoint. This means that `GET` with query parameters is not supported. -It is also preferred that Gremlin scripts be parameterized when possible via `bindings`: +It is also preferred that Gremlin scripts be parameterized when possible via `parameters`: [source,text] -curl -X POST -d "{\"gremlin\":\"100-x\", \"bindings\":{\"x\":1}}" "http://localhost:8182" +curl -X POST -d "{\"gremlin\":\"100-x\", \"parameters\":\"[x:1]\"}" "http://localhost:8182" -The `bindings` argument is a `Map` of variables where the keys become available as variables in the Gremlin script. -Note that parameterization of requests is critical to performance, as repeated script compilation can be avoided on -each request. - -NOTE: It is possible to pass bindings via `GET` based requests. Query string arguments prefixed with "bindings." will -be treated as parameters, where that prefix will be removed and the value following the period will become the -parameter name. In other words, `bindings.x` will create a parameter named "x" that can be referenced in the submitted -Gremlin script. The caveat is that these arguments will always be treated as `String` values. To ensure that data -types are preserved or to pass complex objects such as lists or maps, use `POST` which will at least support the -allowed JSON data types. +The `parameters` argument is a gremlin-lang string that encodes a map of key/value pairs where the keys become available +as variables in the Gremlin script. Note that parameterization of requests is critical to performance, as repeated +script compilation can be avoided on each request. NOTE: The Gremlin Server does not support link:https://en.wikipedia.org/wiki/HTTP_pipelining[HTTP pipelining]. Sending a second request on the same connection before the first response completes will cause the server to close the @@ -845,7 +838,7 @@ Finally, as Gremlin Server can host multiple `ScriptEngine` instances (e.g. `gre possible to define the language to utilize to process the request: [source,text] -curl -X POST -d "{\"gremlin\":\"100-x\", \"language\":\"gremlin-groovy\", \"bindings\":{\"x\":1}}" "http://localhost:8182" +curl -X POST -d "{\"gremlin\":\"100-x\", \"language\":\"gremlin-groovy\", \"parameters\":\"[x:1]\"}" "http://localhost:8182" By default this value is set to `gremlin-groovy`. If using a `GET` operation, this value can be set as a query string argument with by setting the `language` key. @@ -1769,7 +1762,7 @@ continuously: client = Cluster.build("localhost").port(8182).create().connect() ==>org.apache.tinkerpop.gremlin.driver.Client$ClusteredClient@42ff9a77 client.submit("while(true) { }") -org.apache.tinkerpop.gremlin.driver.exception.ResponseException: A timeout occurred during traversal evaluation of [RequestMessage{, fields={bindings={}, language=gremlin-groovy, batchSize=64}, gremlin=while(true) { }}] - consider increasing the limit given to evaluationTimeout +org.apache.tinkerpop.gremlin.driver.exception.ResponseException: A timeout occurred during traversal evaluation of [RequestMessage{, fields={parameters={}, language=gremlin-groovy, batchSize=64}, gremlin=while(true) { }}] - consider increasing the limit given to evaluationTimeout The `GroovyCompilerGremlinPlugin` has a number of configuration options: diff --git a/docs/src/reference/gremlin-variants.asciidoc b/docs/src/reference/gremlin-variants.asciidoc index 51cb6178dee..a001ce52781 100644 --- a/docs/src/reference/gremlin-variants.asciidoc +++ b/docs/src/reference/gremlin-variants.asciidoc @@ -518,14 +518,14 @@ options := new(RequestOptionsBuilder). SetEvaluationTimeout(5000). SetBatchSize(32). SetMaterializeProperties("tokens"). - AddBinding("x", 100). + AddParameter("x", 100). Create() resultSet, err := client.SubmitWithOptions("g.V(x).count()", options) ---- The following options are allowed on a per-request basis in this fashion: `batchSize`, `bulkResults`, `userAgent`, `evaluationTimeout` and `materializeProperties`. -`RequestOptions` may also contain a map of variable `bindings` to be applied to the supplied +`RequestOptions` may also contain a map of query `parameters` to be applied to the supplied traversal string. [source,go] @@ -2316,7 +2316,7 @@ for await (const item of client.stream('g.V()', null)) { } ---- -`client.stream()` accepts the same parameters as `client.submit()`: a script string, optional bindings, and optional +`client.stream()` accepts the same arguments as `client.submit()`: a script string, optional parameters, and optional per-request settings. [source,javascript] diff --git a/docs/src/upgrade/release-4.x.x.asciidoc b/docs/src/upgrade/release-4.x.x.asciidoc index 983c662e4cb..cc7dfe1cec4 100644 --- a/docs/src/upgrade/release-4.x.x.asciidoc +++ b/docs/src/upgrade/release-4.x.x.asciidoc @@ -32,6 +32,39 @@ complete list of all the modifications that are part of this release. === Upgrading for Users +==== Bindings are now Parameters + +The map of named values substituted into a Gremlin query was previously called "bindings" in some places and +"parameters" in others. TinkerPop now refers to these consistently as *query parameters*, reserving "bindings" for +the distinct concept of `ScriptEngine` variable bindings. As a result, the driver methods for supplying query +parameters have been renamed. Update any code that sets them: + +- Java: `RequestMessage.Builder.addBindings(...)` is now `addParameters(...)`. +- Python: `client.submit(..., bindings=...)` is now `submit(..., parameters=...)`, and the `request_options` +key `bindings` is now `parameters`. +- Go: `SetBindings`/`SetBindingsString`/`AddBinding` are now +`SetParameters`/`SetParametersString`/`AddParameter`. +- .NET: `AddBinding`/`AddBindings`/`AddBindingsString` are now +`AddParameter`/`AddParameters`/`AddParametersString`. +- JavaScript: `addBinding`/`addBindings`/`addBindingsString` are now +`addParameter`/`addParameters`/`addParametersString`, and the `RequestOptions.bindings` field is now `parameters`. + +For example, in the Java driver: + +[source,java] +---- +final Map params = new HashMap<>(); +params.put("x", 1); + +// 3.x +RequestMessage.build("g.V(x)").addBindings(params).create(); + +// 4.x +RequestMessage.build("g.V(x)").addParameters(params).create(); +---- + +See: link:https://issues.apache.org/jira/browse/TINKERPOP-3262[TINKERPOP-3262] + ==== Standardizing GLV Connection Options TinkerPop 4.x standardizes connection option names and defaults across all five Gremlin Language Variants (Java, Python, diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClientExtensions.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClientExtensions.cs index 66927c5b171..da13259bb2a 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClientExtensions.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClientExtensions.cs @@ -34,7 +34,7 @@ namespace Gremlin.Net.Driver public static class GremlinClientExtensions { /// - /// Submits a request message that consists of a script with bindings as an asynchronous operation where only a single + /// Submits a request message that consists of a script with parameters as an asynchronous operation where only a single /// result gets returned. /// /// @@ -44,7 +44,7 @@ public static class GremlinClientExtensions /// The type of the expected result. /// The that submits the request. /// The Gremlin request script to send. - /// Bindings for parameters used in the requestScript. + /// Parameters used in the requestScript. /// The token to cancel the operation. The default value is None. /// A single result received from the Gremlin Server. /// @@ -53,10 +53,10 @@ public static class GremlinClientExtensions /// public static async Task SubmitWithSingleResultAsync(this IGremlinClient gremlinClient, string requestScript, - Dictionary? bindings = null, + Dictionary? parameters = null, CancellationToken cancellationToken = default) { - await using var resultSet = await gremlinClient.SubmitAsync(requestScript, bindings, cancellationToken) + await using var resultSet = await gremlinClient.SubmitAsync(requestScript, parameters, cancellationToken) .ConfigureAwait(false); await foreach (var item in resultSet.WithCancellation(cancellationToken).ConfigureAwait(false)) { @@ -94,12 +94,12 @@ public static class GremlinClientExtensions } /// - /// Submits a request message that consists of a script with bindings as an asynchronous operation without returning + /// Submits a request message that consists of a script with parameters as an asynchronous operation without returning /// the result received from the Gremlin Server. /// /// The that submits the request. /// The Gremlin request script to send. - /// Bindings for parameters used in the requestScript. + /// Parameters used in the requestScript. /// The token to cancel the operation. The default value is None. /// The task object representing the asynchronous operation. /// @@ -107,9 +107,9 @@ public static class GremlinClientExtensions /// that an error occurred. /// public static async Task SubmitAsync(this IGremlinClient gremlinClient, string requestScript, - Dictionary? bindings = null, CancellationToken cancellationToken = default) + Dictionary? parameters = null, CancellationToken cancellationToken = default) { - await using var resultSet = await gremlinClient.SubmitAsync(requestScript, bindings, cancellationToken).ConfigureAwait(false); + await using var resultSet = await gremlinClient.SubmitAsync(requestScript, parameters, cancellationToken).ConfigureAwait(false); // Drain the stream to ensure the background task completes and resources are released. await foreach (var _ in resultSet.WithCancellation(cancellationToken).ConfigureAwait(false)) { @@ -139,12 +139,12 @@ public static async Task SubmitAsync(this IGremlinClient gremlinClient, RequestM } /// - /// Submits a request message that consists of a script with bindings as an asynchronous operation. + /// Submits a request message that consists of a script with parameters as an asynchronous operation. /// /// The type of the expected results. /// The that submits the request. /// The Gremlin request script to send. - /// Bindings for parameters used in the requestScript. + /// Parameters used in the requestScript. /// The token to cancel the operation. The default value is None. /// A containing the data and status attributes returned from the server. /// @@ -153,12 +153,12 @@ public static async Task SubmitAsync(this IGremlinClient gremlinClient, RequestM /// public static async Task> SubmitAsync(this IGremlinClient gremlinClient, string requestScript, - Dictionary? bindings = null, + Dictionary? parameters = null, CancellationToken cancellationToken = default) { var msgBuilder = RequestMessage.Build(requestScript); - if (bindings != null) - msgBuilder.AddBindings(bindings); + if (parameters != null) + msgBuilder.AddParameters(parameters); var msg = msgBuilder.Create(); return await gremlinClient.SubmitAsync(msg, cancellationToken).ConfigureAwait(false); } diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/RequestMessage.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/RequestMessage.cs index e843f43d9e4..c301adb701e 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/RequestMessage.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/RequestMessage.cs @@ -48,7 +48,7 @@ private RequestMessage(string gremlin, Dictionary fields) public string Gremlin { get; } /// - /// Gets the fields map containing language, g, bindings, and other options. + /// Gets the fields map containing language, g, parameters, and other options. /// public Dictionary Fields { get; } @@ -84,8 +84,8 @@ public class Builder { private readonly string _gremlin; private readonly Dictionary _fields = new Dictionary(); - private readonly Dictionary _bindings = new Dictionary(); - private string? _bindingsString; + private readonly Dictionary _parameters = new Dictionary(); + private string? _parametersString; internal Builder(string gremlin) { @@ -104,48 +104,48 @@ public Builder AddG(string g) } /// - /// Adds a single binding parameter. + /// Adds a single query parameter. /// - /// The binding key. - /// The binding value. + /// The parameter key. + /// The parameter value. /// The . - public Builder AddBinding(string key, object val) + public Builder AddParameter(string key, object val) { - if (_bindingsString != null) - throw new InvalidOperationException("Cannot mix AddBinding() with AddBindingsString()."); - _bindings[key] = val; + if (_parametersString != null) + throw new InvalidOperationException("Cannot mix AddParameter() with AddParametersString()."); + _parameters[key] = val; return this; } /// - /// Adds multiple binding parameters from a dictionary. The values will be + /// Adds multiple query parameters from a dictionary. The values will be /// converted to a gremlin-lang string when the message is created. - /// Cannot be mixed with . + /// Cannot be mixed with . /// - /// The bindings to add. + /// The parameters to add. /// The . - public Builder AddBindings(Dictionary bindings) + public Builder AddParameters(Dictionary parameters) { - if (_bindingsString != null) - throw new InvalidOperationException("Cannot mix AddBindings() with AddBindingsString()."); - foreach (var kvp in bindings) + if (_parametersString != null) + throw new InvalidOperationException("Cannot mix AddParameters() with AddParametersString()."); + foreach (var kvp in parameters) { - _bindings[kvp.Key] = kvp.Value; + _parameters[kvp.Key] = kvp.Value; } return this; } /// - /// Sets the bindings as a pre-serialized gremlin-lang map literal string. - /// Cannot be mixed with or . + /// Sets the query parameters as a pre-serialized gremlin-lang map literal string. + /// Cannot be mixed with or . /// - /// The gremlin-lang bindings string. + /// The gremlin-lang parameters string. /// The . - public Builder AddBindingsString(string bindingsString) + public Builder AddParametersString(string parametersString) { - if (_bindings.Count > 0) - throw new InvalidOperationException("Cannot mix AddBindingsString() with AddBinding()/AddBindings()."); - _bindingsString = bindingsString; + if (_parameters.Count > 0) + throw new InvalidOperationException("Cannot mix AddParametersString() with AddParameter()/AddParameters()."); + _parametersString = parametersString; return this; } @@ -240,14 +240,14 @@ public Builder AddLanguage(string language) /// The built . public RequestMessage Create() { - // prefer pre-serialized bindings string over raw map - if (_bindingsString != null) + // prefer pre-serialized parameters string over raw map + if (_parametersString != null) { - _fields[Tokens.ArgsBindings] = _bindingsString; + _fields[Tokens.ArgsParameters] = _parametersString; } - else if (_bindings.Count > 0) + else if (_parameters.Count > 0) { - _fields[Tokens.ArgsBindings] = GremlinLang.ConvertParametersToString(_bindings); + _fields[Tokens.ArgsParameters] = GremlinLang.ConvertParametersToString(_parameters); } return new RequestMessage(_gremlin, _fields); } diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteConnection.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteConnection.cs index ec99053b5b1..c473260b5c9 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteConnection.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/DriverRemoteConnection.cs @@ -126,7 +126,7 @@ public async Task> SubmitAsync(GremlinLan var parametersString = gremlinLang.GetParametersAsString(); if (parametersString != "[:]") { - requestMsg.AddBindingsString(parametersString); + requestMsg.AddParametersString(parametersString); } foreach (var optionsStrategy in gremlinLang.OptionsStrategies) diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/TransactionRemoteConnection.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/TransactionRemoteConnection.cs index d63ec834f7d..404f4ffe00f 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/TransactionRemoteConnection.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Remote/TransactionRemoteConnection.cs @@ -68,7 +68,7 @@ public async Task> SubmitAsync(GremlinLan var parametersString = gremlinLang.GetParametersAsString(); if (parametersString != "[:]") { - requestMsg.AddBindingsString(parametersString); + requestMsg.AddParametersString(parametersString); } foreach (var optionsStrategy in gremlinLang.OptionsStrategies) diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs index 7f39308ec00..0f57f873800 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs @@ -47,10 +47,10 @@ public class Tokens public const string ArgsBatchSize = "batchSize"; /// - /// Argument name that allows definition of a map of key/value pairs to apply as variables in the + /// Argument name that allows definition of a map of key/value pairs to apply as query parameters in the /// context of the Gremlin request sent to the server. /// - public const string ArgsBindings = "bindings"; + public const string ArgsParameters = "parameters"; /// /// Argument name that corresponds to the Gremlin to evaluate. diff --git a/gremlin-dotnet/test/Gremlin.Net.Benchmarks/MessageSerializerBenchmarks.cs b/gremlin-dotnet/test/Gremlin.Net.Benchmarks/MessageSerializerBenchmarks.cs index dfbf0082db8..02510f68a93 100644 --- a/gremlin-dotnet/test/Gremlin.Net.Benchmarks/MessageSerializerBenchmarks.cs +++ b/gremlin-dotnet/test/Gremlin.Net.Benchmarks/MessageSerializerBenchmarks.cs @@ -66,7 +66,7 @@ private static GremlinLang BuildSomeGremlinLang() private static RequestMessage RequestMessageFor(GremlinLang gremlinLang) => Gremlin.Net.Driver.Messages.RequestMessage.Build(gremlinLang.GetGremlin()) .AddG("g") - .AddBindings(gremlinLang.Parameters) + .AddParameters(gremlinLang.Parameters) .Create(); private static readonly GraphBinary4MessageSerializer BinaryMessageSerializer = new(); diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference/GremlinApplicationsTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference/GremlinApplicationsTests.cs index 6851e8aa661..29954c80908 100644 --- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference/GremlinApplicationsTests.cs +++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference/GremlinApplicationsTests.cs @@ -40,14 +40,14 @@ public async Task ConnectingViaDriversTest() var gremlinServer = new GremlinServer("localhost", 8182); using (var gremlinClient = new GremlinClient(gremlinServer)) { - var bindings = new Dictionary + var parameters = new Dictionary { {"name", "marko"} }; var response = await gremlinClient.SubmitWithSingleResultAsync("g.V().has('person','name',name).out('knows')", - bindings); + parameters); } // traversal diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs index 5ae086e1390..a35f026522c 100644 --- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs +++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs @@ -164,7 +164,7 @@ public async Task ShouldHandleSimpleScriptWithoutErrors() } [Fact] - public async Task ShouldUseBindingsForScript() + public async Task ShouldUseParametersForScript() { var gremlinServer = new GremlinServer(TestHost, TestPort); using (var gremlinClient = new GremlinClient(gremlinServer)) diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/DriverRemoteConnectionTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/DriverRemoteConnectionTests.cs index e7ea25f6480..fd489fcf929 100644 --- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/DriverRemoteConnectionTests.cs +++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/DriverRemoteConnectionTests.cs @@ -103,7 +103,7 @@ public async Task ShouldBuildRequestWithDefaultLanguage() } [Fact] - public async Task ShouldBuildRequestWithBindings() + public async Task ShouldBuildRequestWithParameters() { RequestMessage? capturedRequest = null; var client = CreateCapturingClient(msg => capturedRequest = msg); @@ -116,8 +116,8 @@ public async Task ShouldBuildRequestWithBindings() await connection.SubmitAsync(gl); Assert.NotNull(capturedRequest); - var bindingsString = (string)capturedRequest!.Fields[Tokens.ArgsBindings]; - Assert.Contains("\"x\":42", bindingsString); + var parametersString = (string)capturedRequest!.Fields[Tokens.ArgsParameters]; + Assert.Contains("\"x\":42", parametersString); } [Fact] diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/HttpRequestContextTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/HttpRequestContextTests.cs index 10522026445..05bcf870f20 100644 --- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/HttpRequestContextTests.cs +++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/HttpRequestContextTests.cs @@ -278,10 +278,10 @@ public void SerializeBodyShouldReflectBodyReplacement() } [Fact] - public void SerializeBodyShouldIncludeBindingsField() + public void SerializeBodyShouldIncludeParametersField() { var message = RequestMessage.Build("g.V(x)") - .AddBindingsString("[x:1,y:'marko']") + .AddParametersString("[x:1,y:'marko']") .Create(); var context = new HttpRequestContext("POST", new Uri("http://localhost:8182/gremlin"), new Dictionary(), message); @@ -289,7 +289,7 @@ public void SerializeBodyShouldIncludeBindingsField() var result = context.SerializeBody(); var json = JsonDocument.Parse(result); - Assert.Equal("[x:1,y:'marko']", json.RootElement.GetProperty("bindings").GetString()); + Assert.Equal("[x:1,y:'marko']", json.RootElement.GetProperty("parameters").GetString()); } #endregion diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/Messages/RequestMessageTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/Messages/RequestMessageTests.cs index 4d669841b56..29a6ac0ff46 100644 --- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/Messages/RequestMessageTests.cs +++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Driver/Messages/RequestMessageTests.cs @@ -55,27 +55,27 @@ public void ShouldSetGField() } [Fact] - public void ShouldSetBindings() + public void ShouldSetParameters() { var msg = RequestMessage.Build("g.V(x)") - .AddBinding("x", 1) + .AddParameter("x", 1) .Create(); - var bindingsString = (string)msg.Fields[Tokens.ArgsBindings]; - Assert.Contains("\"x\":1", bindingsString); + var parametersString = (string)msg.Fields[Tokens.ArgsParameters]; + Assert.Contains("\"x\":1", parametersString); } [Fact] - public void ShouldSetMultipleBindings() + public void ShouldSetMultipleParameters() { - var bindings = new Dictionary { { "x", 1 }, { "name", "test" } }; + var parameters = new Dictionary { { "x", 1 }, { "name", "test" } }; var msg = RequestMessage.Build("g.V(x).has(name)") - .AddBindings(bindings) + .AddParameters(parameters) .Create(); - var bindingsString = (string)msg.Fields[Tokens.ArgsBindings]; - Assert.Contains("\"x\":1", bindingsString); - Assert.Contains("\"name\":\"test\"", bindingsString); + var parametersString = (string)msg.Fields[Tokens.ArgsParameters]; + Assert.Contains("\"x\":1", parametersString); + Assert.Contains("\"name\":\"test\"", parametersString); } [Fact] @@ -99,21 +99,21 @@ public void ShouldReportHasField() } [Fact] - public void ShouldNotContainBindingsWhenNoneAdded() + public void ShouldNotContainParametersWhenNoneAdded() { var msg = RequestMessage.Build("g.V()").Create(); - Assert.False(msg.Fields.ContainsKey(Tokens.ArgsBindings)); + Assert.False(msg.Fields.ContainsKey(Tokens.ArgsParameters)); } [Fact] - public void ShouldSetBindingsString() + public void ShouldSetParametersString() { var msg = RequestMessage.Build("g.V(x)") - .AddBindingsString("[\"x\":1]") + .AddParametersString("[\"x\":1]") .Create(); - Assert.Equal("[\"x\":1]", msg.Fields[Tokens.ArgsBindings]); + Assert.Equal("[\"x\":1]", msg.Fields[Tokens.ArgsParameters]); } } } diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Client.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Client.java index a8b1b49ad69..00c1037cda2 100644 --- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Client.java +++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Client.java @@ -235,7 +235,7 @@ public CompletableFuture submitAsync(final String gremlin, final Requ // apply settings if they were made available options.getTimeout().ifPresent(timeout -> request.addTimeoutMillis(timeout)); - options.getParameters().ifPresent(params -> request.addBindings(params)); + options.getParameters().ifPresent(params -> request.addParameters(params)); options.getG().ifPresent(g -> request.addG(g)); options.getLanguage().ifPresent(lang -> request.addLanguage(lang)); options.getMaterializeProperties().ifPresent(mp -> request.addMaterializeProperties(mp)); diff --git a/gremlin-go/driver/client.go b/gremlin-go/driver/client.go index 08eb7760aad..80e400a25df 100644 --- a/gremlin-go/driver/client.go +++ b/gremlin-go/driver/client.go @@ -273,13 +273,13 @@ func (client *Client) SubmitWithOptions(traversalString string, requestOptions R return rs, err } -// Submit submits a Gremlin script to the server and returns a ResultSet. Submit can optionally accept a map of bindings -// to be applied to the traversalString, it is preferred however to instead wrap any bindings into a RequestOptions +// Submit submits a Gremlin script to the server and returns a ResultSet. Submit can optionally accept a map of parameters +// to be applied to the traversalString, it is preferred however to instead wrap any parameters into a RequestOptions // struct and use SubmitWithOptions(). -func (client *Client) Submit(traversalString string, bindings ...map[string]interface{}) (ResultSet, error) { +func (client *Client) Submit(traversalString string, parameters ...map[string]interface{}) (ResultSet, error) { requestOptionsBuilder := new(RequestOptionsBuilder) - if len(bindings) > 0 { - requestOptionsBuilder.SetBindings(bindings[0]) + if len(parameters) > 0 { + requestOptionsBuilder.SetParameters(parameters[0]) } return client.SubmitWithOptions(traversalString, requestOptionsBuilder.Create()) } @@ -289,7 +289,7 @@ func (client *Client) submitGremlinLang(gremlinLang *GremlinLang) (ResultSet, er return client.submitGremlinLangWithBuilder(gremlinLang, new(RequestOptionsBuilder)) } -// submitGremlinLangWithBuilder is the core submission function. It extracts bindings +// submitGremlinLangWithBuilder is the core submission function. It extracts parameters // and options strategies from the GremlinLang, merges them into the provided builder, // then builds and sends the request. func (client *Client) submitGremlinLangWithBuilder(gremlinLang *GremlinLang, builder *RequestOptionsBuilder) (ResultSet, error) { @@ -297,7 +297,7 @@ func (client *Client) submitGremlinLangWithBuilder(gremlinLang *GremlinLang, bui parametersString := gremlinLang.GetParametersAsString() if parametersString != "[:]" { - builder.SetBindingsString(parametersString) + builder.SetParametersString(parametersString) } if len(gremlinLang.optionsStrategies) > 0 { @@ -320,9 +320,9 @@ func applyOptionsConfig(builder *RequestOptionsBuilder, config map[string]interf builderValue := reflect.ValueOf(builder) // Map configuration keys to setter method names. - // "bindings" is intentionally excluded because bindings are handled separately - // via SetBindingsString in submitGremlinLang, and including it here would - // trigger the mutual exclusion panic between SetBindings and SetBindingsString. + // "parameters" is intentionally excluded because parameters are handled separately + // via SetParametersString in submitGremlinLang, and including it here would + // trigger the mutual exclusion panic between SetParameters and SetParametersString. setterMap := map[string]string{ "evaluationTimeout": "SetEvaluationTimeout", "batchSize": "SetBatchSize", diff --git a/gremlin-go/driver/client_test.go b/gremlin-go/driver/client_test.go index db3c7d6091a..73aff14a880 100644 --- a/gremlin-go/driver/client_test.go +++ b/gremlin-go/driver/client_test.go @@ -89,7 +89,7 @@ func TestClient(t *testing.T) { AssertMarkoVertexWithProperties(t, result) }) - t.Run("Test client.Submit() with bindings", func(t *testing.T) { + t.Run("Test client.Submit() with parameters", func(t *testing.T) { skipTestsIfNotEnabled(t, integrationTestSuiteName, testNoAuthEnable) client, err := NewClient(testNoAuthUrl, func(settings *ClientSettings) { @@ -100,9 +100,9 @@ func TestClient(t *testing.T) { assert.NotNil(t, client) defer client.Close() - bindings := map[string]interface{}{"x": 1} + parameters := map[string]interface{}{"x": 1} - resultSet, err := client.Submit("g.V(x).values(\"name\")", bindings) + resultSet, err := client.Submit("g.V(x).values(\"name\")", parameters) assert.NoError(t, err) assert.NotNil(t, resultSet) @@ -113,7 +113,7 @@ func TestClient(t *testing.T) { assert.Equal(t, "marko", result.Data) }) - t.Run("Test client.SubmitWithOptions() with bindings", func(t *testing.T) { + t.Run("Test client.SubmitWithOptions() with parameters", func(t *testing.T) { skipTestsIfNotEnabled(t, integrationTestSuiteName, testNoAuthEnable) client, err := NewClient(testNoAuthUrl, func(settings *ClientSettings) { @@ -124,9 +124,9 @@ func TestClient(t *testing.T) { assert.NotNil(t, client) defer client.Close() - bindings := map[string]interface{}{"x": 1} + parameters := map[string]interface{}{"x": 1} - resultSet, err := client.SubmitWithOptions("g.V(x).values(\"name\")", new(RequestOptionsBuilder).SetBindings(bindings).Create()) + resultSet, err := client.SubmitWithOptions("g.V(x).values(\"name\")", new(RequestOptionsBuilder).SetParameters(parameters).Create()) assert.NoError(t, err) assert.NotNil(t, resultSet) diff --git a/gremlin-go/driver/gremlinlang_test.go b/gremlin-go/driver/gremlinlang_test.go index 496ae4228f9..f15607ad20d 100644 --- a/gremlin-go/driver/gremlinlang_test.go +++ b/gremlin-go/driver/gremlinlang_test.go @@ -881,10 +881,10 @@ func Test_ConvertParametersToString(t *testing.T) { t.Run("should panic on unsupported type via RequestOptionsBuilder.Create()", func(t *testing.T) { defer func() { if r := recover(); r == nil { - t.Error("expected panic for unsupported type in bindings") + t.Error("expected panic for unsupported type in parameters") } }() - new(RequestOptionsBuilder).SetBindings(map[string]interface{}{"x": struct{}{}}).Create() + new(RequestOptionsBuilder).SetParameters(map[string]interface{}{"x": struct{}{}}).Create() }) } diff --git a/gremlin-go/driver/request.go b/gremlin-go/driver/request.go index ebf375d49bf..402e816e099 100644 --- a/gremlin-go/driver/request.go +++ b/gremlin-go/driver/request.go @@ -34,7 +34,7 @@ type RequestMessage struct { // Parameters: // - stringGremlin: The Gremlin query string to execute // - traversalSource: The name of the traversal source (typically "g") -// - requestOptions: Options such as bindings, timeout, batch size, etc. +// - requestOptions: Options such as parameters, timeout, batch size, etc. // // Returns: // - request: A request structure ready for serialization @@ -52,8 +52,8 @@ func MakeStringRequest(stringGremlin string, traversalSource string, requestOpti "g": traversalSource, } - if requestOptions.bindingsString != "" && requestOptions.bindingsString != "[:]" { - newFields["bindings"] = requestOptions.bindingsString + if requestOptions.parametersString != "" && requestOptions.parametersString != "[:]" { + newFields["parameters"] = requestOptions.parametersString } if requestOptions.evaluationTimeout != 0 { diff --git a/gremlin-go/driver/requestOptions.go b/gremlin-go/driver/requestOptions.go index 53863276d92..b419d13c1a1 100644 --- a/gremlin-go/driver/requestOptions.go +++ b/gremlin-go/driver/requestOptions.go @@ -23,7 +23,7 @@ type RequestOptions struct { evaluationTimeout int batchSize int userAgent string - bindingsString string + parametersString string materializeProperties string bulkResults *bool transactionId string @@ -33,8 +33,8 @@ type RequestOptionsBuilder struct { evaluationTimeout int batchSize int userAgent string - bindings map[string]interface{} - bindingsString string + parameters map[string]interface{} + parametersString string materializeProperties string bulkResults *bool transactionId string @@ -55,19 +55,19 @@ func (builder *RequestOptionsBuilder) SetUserAgent(userAgent string) *RequestOpt return builder } -func (builder *RequestOptionsBuilder) SetBindings(bindings map[string]interface{}) *RequestOptionsBuilder { - if builder.bindingsString != "" { - panic("cannot mix SetBindings() with SetBindingsString()") +func (builder *RequestOptionsBuilder) SetParameters(parameters map[string]interface{}) *RequestOptionsBuilder { + if builder.parametersString != "" { + panic("cannot mix SetParameters() with SetParametersString()") } - builder.bindings = bindings + builder.parameters = parameters return builder } -func (builder *RequestOptionsBuilder) SetBindingsString(bindingsString string) *RequestOptionsBuilder { - if builder.bindings != nil { - panic("cannot mix SetBindingsString() with SetBindings()") +func (builder *RequestOptionsBuilder) SetParametersString(parametersString string) *RequestOptionsBuilder { + if builder.parameters != nil { + panic("cannot mix SetParametersString() with SetParameters()") } - builder.bindingsString = bindingsString + builder.parametersString = parametersString return builder } @@ -86,14 +86,14 @@ func (builder *RequestOptionsBuilder) SetTransactionId(transactionId string) *Re return builder } -func (builder *RequestOptionsBuilder) AddBinding(key string, binding interface{}) *RequestOptionsBuilder { - if builder.bindingsString != "" { - panic("cannot mix AddBinding() with SetBindingsString()") +func (builder *RequestOptionsBuilder) AddParameter(key string, parameter interface{}) *RequestOptionsBuilder { + if builder.parametersString != "" { + panic("cannot mix AddParameter() with SetParametersString()") } - if builder.bindings == nil { - builder.bindings = make(map[string]interface{}) + if builder.parameters == nil { + builder.parameters = make(map[string]interface{}) } - builder.bindings[key] = binding + builder.parameters[key] = parameter return builder } @@ -107,11 +107,11 @@ func (builder *RequestOptionsBuilder) Create() RequestOptions { requestOptions.bulkResults = builder.bulkResults requestOptions.transactionId = builder.transactionId - // convert map bindings to string at creation time, matching Java's RequestOptions.Builder.create() - if builder.bindingsString != "" { - requestOptions.bindingsString = builder.bindingsString - } else if builder.bindings != nil { - requestOptions.bindingsString = ConvertParametersToString(builder.bindings) + // convert map parameters to string at creation time, matching Java's RequestOptions.Builder.create() + if builder.parametersString != "" { + requestOptions.parametersString = builder.parametersString + } else if builder.parameters != nil { + requestOptions.parametersString = ConvertParametersToString(builder.parameters) } return *requestOptions diff --git a/gremlin-go/driver/requestOptions_test.go b/gremlin-go/driver/requestOptions_test.go index 851e4d02e1a..f8e7213de1b 100644 --- a/gremlin-go/driver/requestOptions_test.go +++ b/gremlin-go/driver/requestOptions_test.go @@ -42,33 +42,33 @@ func TestRequestOptions(t *testing.T) { r := new(RequestOptionsBuilder).SetMaterializeProperties("TestMaterializeProperties").Create() assert.Equal(t, "TestMaterializeProperties", r.materializeProperties) }) - t.Run("Test RequestOptionsBuilder with custom bindings", func(t *testing.T) { - bindings := map[string]interface{}{"x": int32(2), "y": int32(5)} - r := new(RequestOptionsBuilder).SetBindings(bindings).Create() - assert.Contains(t, r.bindingsString, "\"x\":2") - assert.Contains(t, r.bindingsString, "\"y\":5") + t.Run("Test RequestOptionsBuilder with custom parameters", func(t *testing.T) { + parameters := map[string]interface{}{"x": int32(2), "y": int32(5)} + r := new(RequestOptionsBuilder).SetParameters(parameters).Create() + assert.Contains(t, r.parametersString, "\"x\":2") + assert.Contains(t, r.parametersString, "\"y\":5") }) - t.Run("Test RequestOptionsBuilder AddBinding() with no other bindings", func(t *testing.T) { - r := new(RequestOptionsBuilder).AddBinding("x", int32(2)).AddBinding("y", int32(5)).Create() - assert.Contains(t, r.bindingsString, "\"x\":2") - assert.Contains(t, r.bindingsString, "\"y\":5") + t.Run("Test RequestOptionsBuilder AddParameter() with no other parameters", func(t *testing.T) { + r := new(RequestOptionsBuilder).AddParameter("x", int32(2)).AddParameter("y", int32(5)).Create() + assert.Contains(t, r.parametersString, "\"x\":2") + assert.Contains(t, r.parametersString, "\"y\":5") }) - t.Run("Test RequestOptionsBuilder AddBinding() overwriting existing key", func(t *testing.T) { - r := new(RequestOptionsBuilder).AddBinding("x", int32(2)).AddBinding("x", int32(5)).Create() - assert.Contains(t, r.bindingsString, "\"x\":5") + t.Run("Test RequestOptionsBuilder AddParameter() overwriting existing key", func(t *testing.T) { + r := new(RequestOptionsBuilder).AddParameter("x", int32(2)).AddParameter("x", int32(5)).Create() + assert.Contains(t, r.parametersString, "\"x\":5") }) - t.Run("Test RequestOptionsBuilder AddBinding() with existing bindings", func(t *testing.T) { - bindings := map[string]interface{}{"x": int32(2), "y": int32(5)} - r := new(RequestOptionsBuilder).SetBindings(bindings).AddBinding("z", int32(7)).Create() - assert.Contains(t, r.bindingsString, "\"x\":2") - assert.Contains(t, r.bindingsString, "\"y\":5") - assert.Contains(t, r.bindingsString, "\"z\":7") + t.Run("Test RequestOptionsBuilder AddParameter() with existing parameters", func(t *testing.T) { + parameters := map[string]interface{}{"x": int32(2), "y": int32(5)} + r := new(RequestOptionsBuilder).SetParameters(parameters).AddParameter("z", int32(7)).Create() + assert.Contains(t, r.parametersString, "\"x\":2") + assert.Contains(t, r.parametersString, "\"y\":5") + assert.Contains(t, r.parametersString, "\"z\":7") }) - t.Run("Test RequestOptionsBuilder SetBindings resets previous bindings", func(t *testing.T) { - bindings1 := map[string]interface{}{"x": int32(2)} - bindings2 := map[string]interface{}{"z": int32(7)} - r := new(RequestOptionsBuilder).SetBindings(bindings1).SetBindings(bindings2).Create() - assert.Contains(t, r.bindingsString, "\"z\":7") - assert.NotContains(t, r.bindingsString, "\"x\"") + t.Run("Test RequestOptionsBuilder SetParameters resets previous parameters", func(t *testing.T) { + parameters1 := map[string]interface{}{"x": int32(2)} + parameters2 := map[string]interface{}{"z": int32(7)} + r := new(RequestOptionsBuilder).SetParameters(parameters1).SetParameters(parameters2).Create() + assert.Contains(t, r.parametersString, "\"z\":7") + assert.NotContains(t, r.parametersString, "\"x\"") }) } diff --git a/gremlin-go/driver/request_test.go b/gremlin-go/driver/request_test.go index f1752b0f6c7..a738d627a69 100644 --- a/gremlin-go/driver/request_test.go +++ b/gremlin-go/driver/request_test.go @@ -26,12 +26,12 @@ import ( ) func TestRequest(t *testing.T) { - t.Run("Test makeStringRequest() with no bindings", func(t *testing.T) { + t.Run("Test makeStringRequest() with no parameters", func(t *testing.T) { r := MakeStringRequest("g.V()", "g", *new(RequestOptions)) assert.Equal(t, "g.V()", r.Gremlin) assert.Equal(t, "g", r.Fields["g"]) assert.Equal(t, "gremlin-lang", r.Fields["language"]) - assert.Nil(t, r.Fields["bindings"]) + assert.Nil(t, r.Fields["parameters"]) }) t.Run("Test makeStringRequest() with custom evaluationTimeout", func(t *testing.T) { @@ -58,32 +58,32 @@ func TestRequest(t *testing.T) { assert.Equal(t, true, r.Fields["bulkResults"]) }) - t.Run("Test makeStringRequest() with string bindings", func(t *testing.T) { + t.Run("Test makeStringRequest() with string parameters", func(t *testing.T) { r := MakeStringRequest("g.V(x)", "g", - new(RequestOptionsBuilder).SetBindingsString("[\"x\":1]").Create()) - assert.Equal(t, "[\"x\":1]", r.Fields["bindings"]) + new(RequestOptionsBuilder).SetParametersString("[\"x\":1]").Create()) + assert.Equal(t, "[\"x\":1]", r.Fields["parameters"]) }) - t.Run("Test makeStringRequest() with map bindings converted to string", func(t *testing.T) { + t.Run("Test makeStringRequest() with map parameters converted to string", func(t *testing.T) { r := MakeStringRequest("g.V(x)", "g", - new(RequestOptionsBuilder).SetBindings(map[string]interface{}{"x": int32(1)}).Create()) - assert.Contains(t, r.Fields["bindings"], "\"x\":1") + new(RequestOptionsBuilder).SetParameters(map[string]interface{}{"x": int32(1)}).Create()) + assert.Contains(t, r.Fields["parameters"], "\"x\":1") }) - t.Run("Test RequestOptionsBuilder.Create() converts map bindings to string", func(t *testing.T) { - opts := new(RequestOptionsBuilder).SetBindings(map[string]interface{}{"x": int32(1)}).Create() - assert.NotEmpty(t, opts.bindingsString) - assert.Contains(t, opts.bindingsString, "\"x\":1") + t.Run("Test RequestOptionsBuilder.Create() converts map parameters to string", func(t *testing.T) { + opts := new(RequestOptionsBuilder).SetParameters(map[string]interface{}{"x": int32(1)}).Create() + assert.NotEmpty(t, opts.parametersString) + assert.Contains(t, opts.parametersString, "\"x\":1") }) - t.Run("Test RequestOptionsBuilder rejects mixing SetBindings and SetBindingsString", func(t *testing.T) { + t.Run("Test RequestOptionsBuilder rejects mixing SetParameters and SetParametersString", func(t *testing.T) { defer func() { if r := recover(); r == nil { - t.Error("expected panic when mixing SetBindings and SetBindingsString") + t.Error("expected panic when mixing SetParameters and SetParametersString") } }() new(RequestOptionsBuilder). - SetBindings(map[string]interface{}{"x": int32(1)}). - SetBindingsString("[\"y\":2]") + SetParameters(map[string]interface{}{"x": int32(1)}). + SetParametersString("[\"y\":2]") }) } diff --git a/gremlin-js/gremlin-javascript/lib/driver/client.ts b/gremlin-js/gremlin-javascript/lib/driver/client.ts index b13493b208e..131e7ae8d68 100644 --- a/gremlin-js/gremlin-javascript/lib/driver/client.ts +++ b/gremlin-js/gremlin-javascript/lib/driver/client.ts @@ -22,7 +22,7 @@ import {RequestMessage} from "./request-message.js"; import { Transaction } from '../process/transaction.js'; export type RequestOptions = { - bindings?: any; + parameters?: any; language?: string; accept?: string; evaluationTimeout?: number; @@ -78,12 +78,12 @@ export default class Client { /** * Send a request to the Gremlin Server and buffer the entire response. * @param {string} message The script to send - * @param {Object|null} [bindings] The script bindings, if any. + * @param {Object|null} [parameters] The query parameters, if any. * @param {RequestOptions} [requestOptions] Configuration specific to the current request. * @returns {Promise} */ - submit(message: string, bindings: any | null, requestOptions?: RequestOptions): Promise { - return this._connection.submit(this.#buildRequest(message, bindings, requestOptions)); + submit(message: string, parameters: any | null, requestOptions?: RequestOptions): Promise { + return this._connection.submit(this.#buildRequest(message, parameters, requestOptions)); } /** @@ -91,33 +91,33 @@ export default class Client { * Returns an AsyncGenerator that yields individual result items as they are * deserialized from the response. For bulked responses, yields Traverser objects. * @param {string} message The script to send - * @param {Object|null} [bindings] The script bindings, if any. + * @param {Object|null} [parameters] The query parameters, if any. * @param {RequestOptions} [requestOptions] Configuration specific to the current request. * @returns {AsyncGenerator} */ - async *stream(message: string, bindings: any | null, requestOptions?: RequestOptions): AsyncGenerator { - return yield* this._connection.stream(this.#buildRequest(message, bindings, requestOptions)); + async *stream(message: string, parameters: any | null, requestOptions?: RequestOptions): AsyncGenerator { + return yield* this._connection.stream(this.#buildRequest(message, parameters, requestOptions)); } - #buildRequest(message: string, bindings: any | null, requestOptions?: RequestOptions): RequestMessage { + #buildRequest(message: string, parameters: any | null, requestOptions?: RequestOptions): RequestMessage { const requestBuilder = RequestMessage.build(message) .addG(this.options.traversalSource || 'g'); if (requestOptions?.language) { requestBuilder.addLanguage(requestOptions.language); } - if (requestOptions?.bindings) { - if (typeof requestOptions.bindings === 'string') { - requestBuilder.addBindingsString(requestOptions.bindings); + if (requestOptions?.parameters) { + if (typeof requestOptions.parameters === 'string') { + requestBuilder.addParametersString(requestOptions.parameters); } else { - requestBuilder.addBindings(requestOptions.bindings); + requestBuilder.addParameters(requestOptions.parameters); } } - if (bindings) { - if (typeof bindings === 'string') { - requestBuilder.addBindingsString(bindings); + if (parameters) { + if (typeof parameters === 'string') { + requestBuilder.addParametersString(parameters); } else { - requestBuilder.addBindings(bindings); + requestBuilder.addParameters(parameters); } } if (requestOptions?.materializeProperties) { diff --git a/gremlin-js/gremlin-javascript/lib/driver/driver-remote-connection.ts b/gremlin-js/gremlin-javascript/lib/driver/driver-remote-connection.ts index 78caf3bec89..06e2f8c6490 100644 --- a/gremlin-js/gremlin-javascript/lib/driver/driver-remote-connection.ts +++ b/gremlin-js/gremlin-javascript/lib/driver/driver-remote-connection.ts @@ -109,7 +109,7 @@ export default class DriverRemoteConnection extends RemoteConnection { const parametersString = gremlinLang.getParametersAsString(); if (parametersString !== '[:]') { - requestOptions.bindings = parametersString; + requestOptions.parameters = parametersString; } // If this connection is bound to a transaction, attach the transactionId diff --git a/gremlin-js/gremlin-javascript/lib/driver/request-message.ts b/gremlin-js/gremlin-javascript/lib/driver/request-message.ts index 29dc55219c6..9064b524b0f 100644 --- a/gremlin-js/gremlin-javascript/lib/driver/request-message.ts +++ b/gremlin-js/gremlin-javascript/lib/driver/request-message.ts @@ -22,7 +22,7 @@ import GremlinLang from '../process/gremlin-lang.js'; // Token constants const Tokens = { ARGS_LANGUAGE: 'language', - ARGS_BINDINGS: 'bindings', + ARGS_PARAMETERS: 'parameters', ARGS_G: 'g', ARGS_MATERIALIZE_PROPERTIES: 'materializeProperties', TIMEOUT_MS: 'timeoutMs', @@ -39,7 +39,7 @@ export class RequestMessage { private gremlin: string; private language: string; private timeoutMs?: number; - private bindings?: object; + private parameters?: object; private g?: string; private materializeProperties?: string; private bulkResults?: boolean; @@ -50,7 +50,7 @@ export class RequestMessage { gremlin: string, language: string, timeoutMs: number | undefined, - bindings: object | undefined, + parameters: object | undefined, g: string | undefined, materializeProperties: string | undefined, bulkResults: boolean | undefined, @@ -64,7 +64,7 @@ export class RequestMessage { this.gremlin = gremlin; this.language = language; this.timeoutMs = timeoutMs; - this.bindings = bindings; + this.parameters = parameters; this.g = g; this.materializeProperties = materializeProperties; this.bulkResults = bulkResults; @@ -84,8 +84,8 @@ export class RequestMessage { return this.timeoutMs; } - getBindings(): object | undefined { - return this.bindings; + getParameters(): object | undefined { + return this.parameters; } getG(): string | undefined { @@ -125,8 +125,8 @@ export class RequestMessage { if (this.g) { payload['g'] = this.g; } - if (this.bindings !== undefined) { - payload['bindings'] = this.bindings; + if (this.parameters !== undefined) { + payload['parameters'] = this.parameters; } if (this.timeoutMs !== undefined) { payload['timeoutMs'] = this.timeoutMs; @@ -159,8 +159,8 @@ export class RequestMessage { */ export class Builder { private readonly gremlin: string; - private readonly bindings = {}; - private bindingsString?: string; + private readonly parameters = {}; + private parametersString?: string; public language: string; public timeoutMs?: number; public g?: string; @@ -181,36 +181,36 @@ export class Builder { } /** - * Adds a single binding parameter. The accumulated bindings map is converted to a gremlin-lang + * Adds a single query parameter. The accumulated parameters map is converted to a gremlin-lang * map literal string when the message is created. - * Cannot be mixed with {@link addBindingsString}. + * Cannot be mixed with {@link addParametersString}. */ - addBinding(key: string, value: any): Builder { - if (this.bindingsString) throw new Error('Cannot mix addBinding() with addBindingsString().'); - Object.assign(this.bindings, {[key]: value}) + addParameter(key: string, value: any): Builder { + if (this.parametersString) throw new Error('Cannot mix addParameter() with addParametersString().'); + Object.assign(this.parameters, {[key]: value}) return this; } /** - * Merges the provided bindings into the accumulated bindings map. The values are converted to a + * Merges the provided parameters into the accumulated parameters map. The values are converted to a * gremlin-lang map literal string when the message is created. - * Cannot be mixed with {@link addBindingsString}. + * Cannot be mixed with {@link addParametersString}. */ - addBindings(otherBindings: object): Builder { - if (!otherBindings) throw new Error('bindings argument cannot be null.'); - if (this.bindingsString) throw new Error('Cannot mix addBindings() with addBindingsString().'); - Object.assign(this.bindings, otherBindings) + addParameters(otherParameters: object): Builder { + if (!otherParameters) throw new Error('parameters argument cannot be null.'); + if (this.parametersString) throw new Error('Cannot mix addParameters() with addParametersString().'); + Object.assign(this.parameters, otherParameters) return this; } /** - * Sets the bindings as a pre-formatted gremlin-lang map literal string (e.g. `'["x":1,"y":"knows"]'`). - * Calling this method replaces any previously set bindings string (last-one-wins). - * Cannot be mixed with {@link addBinding} or {@link addBindings}. + * Sets the query parameters as a pre-formatted gremlin-lang map literal string (e.g. `'["x":1,"y":"knows"]'`). + * Calling this method replaces any previously set parameters string (last-one-wins). + * Cannot be mixed with {@link addParameter} or {@link addParameters}. */ - addBindingsString(bindingsString: string): Builder { - if (Object.keys(this.bindings).length > 0) throw new Error('Cannot mix addBindingsString() with addBinding()/addBindings().'); - this.bindingsString = bindingsString; + addParametersString(parametersString: string): Builder { + if (Object.keys(this.parameters).length > 0) throw new Error('Cannot mix addParametersString() with addParameter()/addParameters().'); + this.parametersString = parametersString; return this; } @@ -257,20 +257,20 @@ export class Builder { * Create the request message given the settings provided to the Builder. */ create(): RequestMessage { - // mutual exclusion between addBindings/addBinding and addBindingsString is + // mutual exclusion between addParameters/addParameter and addParametersString is // enforced at call time, so only one path can be set here - let bindings: string | undefined; - if (this.bindingsString) { - bindings = this.bindingsString; - } else if (Object.keys(this.bindings).length > 0) { - bindings = GremlinLang.convertParametersToString(new Map(Object.entries(this.bindings))); + let parameters: string | undefined; + if (this.parametersString) { + parameters = this.parametersString; + } else if (Object.keys(this.parameters).length > 0) { + parameters = GremlinLang.convertParametersToString(new Map(Object.entries(this.parameters))); } // @ts-ignore - accessing private constructor from Builder return new RequestMessage( this.gremlin, this.language || 'gremlin-lang', this.timeoutMs, - bindings, + parameters, this.g, this.materializeProperties, this.bulkResults, diff --git a/gremlin-js/gremlin-javascript/lib/process/transaction.ts b/gremlin-js/gremlin-javascript/lib/process/transaction.ts index 57b77022b27..0ce89842277 100644 --- a/gremlin-js/gremlin-javascript/lib/process/transaction.ts +++ b/gremlin-js/gremlin-javascript/lib/process/transaction.ts @@ -160,7 +160,7 @@ export class Transaction { * Submits a gremlin-lang string within this transaction. The transactionId * is automatically attached. Has the same signature as Client.submit(). */ - async submit(gremlin: string, bindings?: any, requestOptions?: any): Promise { + async submit(gremlin: string, parameters?: any, requestOptions?: any): Promise { if (!this._isOpen) { throw new Error('Transaction is not open'); } @@ -168,7 +168,7 @@ export class Transaction { ...requestOptions, transactionId: this._transactionId, }; - return this._client.submit(gremlin, bindings || null, opts); + return this._client.submit(gremlin, parameters || null, opts); } async #closeTransaction(script: string): Promise { diff --git a/gremlin-js/gremlin-javascript/lib/structure/io/binary/internals/GraphBinaryWriter.js b/gremlin-js/gremlin-javascript/lib/structure/io/binary/internals/GraphBinaryWriter.js index 5a9cae0db8a..d9a1d8f7927 100644 --- a/gremlin-js/gremlin-javascript/lib/structure/io/binary/internals/GraphBinaryWriter.js +++ b/gremlin-js/gremlin-javascript/lib/structure/io/binary/internals/GraphBinaryWriter.js @@ -48,9 +48,9 @@ export default class GraphBinaryWriter { if (g) { fields.set('g', g); } - const bindings = requestMessage.getBindings(); - if (bindings && Object.keys(bindings).length > 0) { - fields.set('bindings', bindings); + const parameters = requestMessage.getParameters(); + if (parameters && Object.keys(parameters).length > 0) { + fields.set('parameters', parameters); } const timeoutMs = requestMessage.getTimeoutMs(); if (timeoutMs !== undefined) { diff --git a/gremlin-js/gremlin-javascript/test/integration/client-tests.js b/gremlin-js/gremlin-javascript/test/integration/client-tests.js index 32a3fb4468f..9194fa20221 100644 --- a/gremlin-js/gremlin-javascript/test/integration/client-tests.js +++ b/gremlin-js/gremlin-javascript/test/integration/client-tests.js @@ -45,7 +45,7 @@ describe('Client', function () { assert.ok(result.first() instanceof Vertex); }); }); - it('should send and parse a script with bindings', function () { + it('should send and parse a script with parameters', function () { return client.submit('g.V().has("name", x).values("age")', { x: 'marko' }) .then(function (result) { assert.ok(result); diff --git a/gremlin-python/src/main/python/gremlin_python/driver/client.py b/gremlin-python/src/main/python/gremlin_python/driver/client.py index 7cb073f696c..6f39f59c6c0 100644 --- a/gremlin-python/src/main/python/gremlin_python/driver/client.py +++ b/gremlin-python/src/main/python/gremlin_python/driver/client.py @@ -153,31 +153,30 @@ def _get_connection(self): max_connections=self._max_connections, **self._transport_kwargs) - def submit(self, message, bindings=None, request_options=None): - return self.submit_async(message, bindings=bindings, request_options=request_options).result() + def submit(self, message, parameters=None, request_options=None): + return self.submit_async(message, parameters=parameters, request_options=request_options).result() - def submitAsync(self, message, bindings=None, request_options=None): + def submitAsync(self, message, parameters=None, request_options=None): warnings.warn( "gremlin_python.driver.client.Client.submitAsync will be replaced by " "gremlin_python.driver.client.Client.submit_async.", DeprecationWarning) - return self.submit_async(message, bindings, request_options) + return self.submit_async(message, parameters, request_options) - def submit_async(self, message, bindings=None, request_options=None): + def submit_async(self, message, parameters=None, request_options=None): if self.is_closed(): raise Exception("Client is closed") log.debug("message '%s'", str(message)) fields = {'g': self._traversal_source} - # TODO: bindings is now part of request_options, evaluate the need to keep it separate in python. - # Note this bindings parameter only applies to string script submissions - if isinstance(message, str) and bindings: + # Note this parameters argument only applies to string script submissions + if isinstance(message, str) and parameters: from gremlin_python.process.traversal import GremlinLang - if isinstance(bindings, dict): - fields['bindings'] = GremlinLang.convert_parameters_to_string(bindings) + if isinstance(parameters, dict): + fields['parameters'] = GremlinLang.convert_parameters_to_string(parameters) else: - fields['bindings'] = bindings + fields['parameters'] = parameters if isinstance(message, str): log.debug("fields='%s', gremlin='%s'", str(fields), str(message)) @@ -194,13 +193,13 @@ def submit_async(self, message, bindings=None, request_options=None): conn = self._pool.get(True) if request_options: message.fields.update({token: request_options[token] for token in request.Tokens - if token in request_options and token != 'bindings'}) - if 'bindings' in request_options: - bindings_val = request_options['bindings'] - if isinstance(bindings_val, dict): + if token in request_options and token != 'parameters'}) + if 'parameters' in request_options: + parameters_val = request_options['parameters'] + if isinstance(parameters_val, dict): from gremlin_python.process.traversal import GremlinLang - bindings_val = GremlinLang.convert_parameters_to_string(bindings_val) - message.fields['bindings'] = bindings_val + parameters_val = GremlinLang.convert_parameters_to_string(parameters_val) + message.fields['parameters'] = parameters_val # Fill in the connection-level default batch size when the caller did # not set a per-request batchSize. diff --git a/gremlin-python/src/main/python/gremlin_python/driver/driver_remote_connection.py b/gremlin-python/src/main/python/gremlin_python/driver/driver_remote_connection.py index 3c0f094569e..e911720a3a2 100644 --- a/gremlin-python/src/main/python/gremlin_python/driver/driver_remote_connection.py +++ b/gremlin-python/src/main/python/gremlin_python/driver/driver_remote_connection.py @@ -75,12 +75,12 @@ def submit(self, gremlin_lang): request_options=self.extract_request_options(gremlin_lang)) return RemoteTraversal(result_set) - def submitAsync(self, message, bindings=None, request_options=None): + def submitAsync(self, message, parameters=None, request_options=None): warnings.warn( "gremlin_python.driver.driver_remote_connection.DriverRemoteConnection.submitAsync will be replaced by " "gremlin_python.driver.driver_remote_connection.DriverRemoteConnection.submit_async.", DeprecationWarning) - self.submit_async(message, bindings, request_options) + self.submit_async(message, parameters, request_options) def submit_async(self, gremlin_lang): log.debug("submit_async with gremlin lang script '%s'", gremlin_lang.get_gremlin()) @@ -114,6 +114,6 @@ def extract_request_options(gremlin_lang): parameters_string = gremlin_lang.get_parameters_as_string() if parameters_string != '[:]': - request_options["bindings"] = parameters_string + request_options["parameters"] = parameters_string return request_options diff --git a/gremlin-python/src/main/python/gremlin_python/driver/request.py b/gremlin-python/src/main/python/gremlin_python/driver/request.py index 119c76c0a94..b596cfccb54 100644 --- a/gremlin-python/src/main/python/gremlin_python/driver/request.py +++ b/gremlin-python/src/main/python/gremlin_python/driver/request.py @@ -23,6 +23,6 @@ RequestMessage = collections.namedtuple( 'RequestMessage', ['fields', 'gremlin']) -Tokens = ['batchSize', 'bindings', 'g', 'gremlin', 'language', +Tokens = ['batchSize', 'parameters', 'g', 'gremlin', 'language', 'evaluationTimeout', 'materializeProperties', 'timeoutMs', 'userAgent', 'bulkResults', 'transactionId'] diff --git a/gremlin-python/src/main/python/gremlin_python/driver/transaction.py b/gremlin-python/src/main/python/gremlin_python/driver/transaction.py index 857f1a2e3d6..d83ded122bc 100644 --- a/gremlin-python/src/main/python/gremlin_python/driver/transaction.py +++ b/gremlin-python/src/main/python/gremlin_python/driver/transaction.py @@ -98,7 +98,7 @@ def begin(self): strategies.add_strategies([RemoteStrategy(tx_connection)]) return GraphTraversalSource(None, strategies, GremlinLang()) - def submit(self, gremlin, bindings=None, request_options=None): + def submit(self, gremlin, parameters=None, request_options=None): """Submits a gremlin-lang string within this transaction. The transactionId is automatically attached. Has the same signature @@ -109,7 +109,7 @@ def submit(self, gremlin, bindings=None, request_options=None): opts = {'transactionId': self._transaction_id} if request_options: opts.update(request_options) - return self._client.submit(gremlin, bindings=bindings, request_options=opts) + return self._client.submit(gremlin, parameters=parameters, request_options=opts) def commit(self): """Commits the transaction.""" diff --git a/gremlin-python/src/main/python/tests/integration/driver/test_client.py b/gremlin-python/src/main/python/tests/integration/driver/test_client.py index 5afefa11979..308c010219b 100644 --- a/gremlin-python/src/main/python/tests/integration/driver/test_client.py +++ b/gremlin-python/src/main/python/tests/integration/driver/test_client.py @@ -97,7 +97,7 @@ def capture(http_request): client.close() -def test_client_simple_eval_bindings(client): +def test_client_simple_eval_parameters(client): assert client.submit('g.V(x).values("age")', {'x': 1}).all().result()[0] == 29 @@ -105,18 +105,18 @@ def test_client_eval_traversal(client): assert len(client.submit('g.V()').all().result()) == 6 -def test_client_eval_traversal_bindings(client): - assert client.submit('g.V(x).values("name")', bindings={'x': 1}).all().result()[0] == 'marko' +def test_client_eval_traversal_parameters(client): + assert client.submit('g.V(x).values("name")', parameters={'x': 1}).all().result()[0] == 'marko' -def test_client_eval_traversal_request_options_bindings(client): - assert client.submit('g.V(x).values("name")', request_options={'bindings': {'x': 1}}).all().result()[0] == 'marko' +def test_client_eval_traversal_request_options_parameters(client): + assert client.submit('g.V(x).values("name")', request_options={'parameters': {'x': 1}}).all().result()[0] == 'marko' -def test_client_eval_traversal_bindings_request_options_bindings(client): - # Note that parameters from request_options[bindings] is applied later and will replace bindings if key is the same - assert client.submit('g.V(x).values("name")', bindings={'x': 1}, - request_options={'bindings': {'x': 2}}).all().result()[0] == 'vadas' +def test_client_eval_traversal_parameters_request_options_parameters(client): + # Note that parameters from request_options[parameters] is applied later and will replace parameters if key is the same + assert client.submit('g.V(x).values("name")', parameters={'x': 1}, + request_options={'parameters': {'x': 2}}).all().result()[0] == 'vadas' def test_client_error(client): @@ -272,22 +272,22 @@ def test_client_gremlin_lang_options(client): assert len(result_set.all().result()) == 6 -def test_client_gremlin_lang_request_options_with_binding(client): +def test_client_gremlin_lang_request_options_with_parameter(client): g = GraphTraversalSource(Graph(), TraversalStrategies()) - # Note that bindings for constructed traversals is done via Parameter only + # Note that parameters for constructed traversals is done via Parameter only t = g.with_('language', 'gremlin-lang').V(GValue('x', [1, 2, 3])).count() - request_opts = {'language': 'gremlin-lang', 'bindings': {'x': [1, 2, 3]}} + request_opts = {'language': 'gremlin-lang', 'parameters': {'x': [1, 2, 3]}} message = create_basic_request_message(t) result_set = client.submit(message, request_options=request_opts) assert result_set.all().result()[0] == 3 # We can re-use the extracted request options in script submission result_set = client.submit('g.V(x).values("name")', request_options=request_opts) assert result_set.all().result()[0] == 'marko' - # For script submission only, we can also add bindings to request options and they will be applied - request_opts2 = {'language': 'gremlin-lang', 'bindings': {'y': 4}} + # For script submission only, we can also add parameters to request options and they will be applied + request_opts2 = {'language': 'gremlin-lang', 'parameters': {'y': 4}} result_set = client.submit('g.V(y).values("name")', request_options=request_opts2) assert result_set.all().result()[0] == 'josh' - result_set = client.submit('g.V(z).values("name")', bindings={'z': 5}) + result_set = client.submit('g.V(z).values("name")', parameters={'z': 5}) assert result_set.all().result()[0] == 'ripple' diff --git a/gremlin-python/src/main/python/tests/integration/driver/test_driver_remote_connection.py b/gremlin-python/src/main/python/tests/integration/driver/test_driver_remote_connection.py index ac852114830..3ca85e66f44 100644 --- a/gremlin-python/src/main/python/tests/integration/driver/test_driver_remote_connection.py +++ b/gremlin-python/src/main/python/tests/integration/driver/test_driver_remote_connection.py @@ -62,7 +62,7 @@ def test_extract_request_options_with_params(self, remote_connection): 'evaluationTimeout': 1000, 'userAgent': 'test', 'bulkResults': True, - 'bindings': "['ids':[1,2,3]]"} + 'parameters': "['ids':[1,2,3]]"} assert 3 == t.to_list()[0] def test_traversals(self, remote_connection): diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java index eed9428c1d9..4540de73037 100644 --- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java +++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java @@ -124,10 +124,10 @@ public class HttpGremlinEndpointHandler extends SimpleChannelInboundHandler INVALID_BINDINGS_KEYS = new HashSet<>(); + protected static final Set INVALID_PARAMETERS_KEYS = new HashSet<>(); static { - INVALID_BINDINGS_KEYS.addAll(Arrays.asList( + INVALID_PARAMETERS_KEYS.addAll(Arrays.asList( T.id.name(), T.key.name(), T.label.name(), T.value.name(), T.id.getAccessor(), T.key.getAccessor(), @@ -136,23 +136,23 @@ public class HttpGremlinEndpointHandler extends SimpleChannelInboundHandler evalFuture = new FutureTask<>(() -> { try { - logger.debug("Processing request containing script [{}] and bindings of [{}] on {}", + logger.debug("Processing request containing script [{}] and parameters of [{}] on {}", requestMessage.getFieldOrDefault(Tokens.ARGS_GREMLIN, ""), - requestMessage.getFieldOrDefault(Tokens.ARGS_BINDINGS, "[:]"), + requestMessage.getFieldOrDefault(Tokens.ARGS_PARAMETERS, "[:]"), Thread.currentThread().getName()); if (settings.enableAuditLog) { AuthenticatedUser user = ctx.channel().attr(StateKey.AUTHENTICATED_USER).get(); @@ -254,30 +254,30 @@ public void channelRead0(final ChannelHandlerContext ctx, final RequestMessage r throw new ProcessingException(GremlinError.scriptEngineNotAvailable(language)); } - // Guard against bad parameters while trying to parse string-based bindings into a Map - if (requestMessage.optionalField(Tokens.ARGS_BINDINGS).isPresent()) { - Map bindings = null; - final String bindingsString = (String) requestMessage.getFields().get(Tokens.ARGS_BINDINGS); + // Guard against bad parameters while trying to parse string-based parameters into a Map + if (requestMessage.optionalField(Tokens.ARGS_PARAMETERS).isPresent()) { + Map parameters = null; + final String parametersString = (String) requestMessage.getFields().get(Tokens.ARGS_PARAMETERS); try { - bindings = GremlinQueryParser.parseParameters(bindingsString); + parameters = GremlinQueryParser.parseParameters(parametersString); } catch (GremlinParserException e) { - throw new ProcessingException(GremlinError.incorrectParameterFormat(bindingsString, e)); + throw new ProcessingException(GremlinError.incorrectParameterFormat(parametersString, e)); } if ("gremlin-groovy".equals(language)) { - final Set badBindings = IteratorUtils.set(IteratorUtils.filter( - bindings.keySet().iterator(), - INVALID_BINDINGS_KEYS::contains)); - if (!badBindings.isEmpty()) { - throw new ProcessingException(GremlinError.binding(badBindings)); + final Set badParameters = IteratorUtils.set(IteratorUtils.filter( + parameters.keySet().iterator(), + INVALID_PARAMETERS_KEYS::contains)); + if (!badParameters.isEmpty()) { + throw new ProcessingException(GremlinError.parameter(badParameters)); } } - if (bindings.size() > settings.maxParameters) { - throw new ProcessingException(GremlinError.binding(bindings.size(), settings.maxParameters)); + if (parameters.size() > settings.maxParameters) { + throw new ProcessingException(GremlinError.parameter(parameters.size(), settings.maxParameters)); } - requestCtx.setParameters(bindings); + requestCtx.setParameters(parameters); } // Send back the 200 OK response header here since the response is always chunk transfer encoded. Any diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpRequestMessageDecoder.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpRequestMessageDecoder.java index 8a688b6d6bd..a47683fbf56 100644 --- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpRequestMessageDecoder.java +++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpRequestMessageDecoder.java @@ -189,8 +189,8 @@ private RequestMessage getRequestMessageFromHttpRequest(final FullHttpRequest re final RequestMessage.Builder builder = RequestMessage.build(scriptNode.asText()); - final JsonNode bindingsNode = body.get(Tokens.ARGS_BINDINGS); - if (bindingsNode != null) builder.addBindings(bindingsNode.asText()); + final JsonNode parametersNode = body.get(Tokens.ARGS_PARAMETERS); + if (parametersNode != null) builder.addParameters(parametersNode.asText()); final JsonNode gNode = body.get(Tokens.ARGS_G); if (null != gNode) builder.addG(gNode.asText()); diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/GremlinError.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/GremlinError.java index e0e74c26d0c..301a26f5b95 100644 --- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/GremlinError.java +++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/util/GremlinError.java @@ -64,8 +64,8 @@ public static GremlinError invalidGremlinType(final RequestMessage requestMessag } // script errors - public static GremlinError binding() { - final String message = String.format("The message is using one or more invalid binding keys - they must be of type String and cannot be null"); + public static GremlinError parameter() { + final String message = String.format("The message is using one or more invalid parameter keys - they must be of type String and cannot be null"); return new GremlinError(HttpResponseStatus.BAD_REQUEST, message, "InvalidRequestException"); } @@ -76,15 +76,15 @@ public static GremlinError incorrectParameterFormat(final String parameters, fin return new GremlinError(HttpResponseStatus.BAD_REQUEST, message, "InvalidRequestException"); } - public static GremlinError binding(final Set badBindings) { + public static GremlinError parameter(final Set badParameters) { final String message = String.format("The message supplies one or more invalid parameters key of [%s] - these are reserved names.", - badBindings); + badParameters); return new GremlinError(HttpResponseStatus.BAD_REQUEST, message, "InvalidRequestException"); } - public static GremlinError binding(final int bindingsCount, final int allowedSize) { - final String message = String.format("The message contains %s bindings which is more than is allowed by the server %s configuration", - bindingsCount, allowedSize); + public static GremlinError parameter(final int parametersCount, final int allowedSize) { + final String message = String.format("The message contains %s parameters which is more than is allowed by the server %s configuration", + parametersCount, allowedSize); return new GremlinError(HttpResponseStatus.BAD_REQUEST, message, "InvalidRequestException"); } diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java index c67a0add0d3..e381d6c46a4 100644 --- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java +++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java @@ -193,7 +193,7 @@ public void should413OnPostWithResultTooLarge() throws Exception { final HttpPost httppost = new HttpPost(TestClientFactory.createURLString()); httppost.addHeader("Content-Type", "application/json"); final String bigPost = RandomStringUtils.random(32); - httppost.setEntity(new StringEntity("{\"gremlin\":\""+ String.format("g.inject('%s')", bigPost) + "\", \"bindings\":{\"x\":\"10\"}}", Consts.UTF_8)); + httppost.setEntity(new StringEntity("{\"gremlin\":\""+ String.format("g.inject('%s')", bigPost) + "\", \"parameters\":{\"x\":\"10\"}}", Consts.UTF_8)); try (final CloseableHttpResponse response = httpclient.execute(httppost)) { assertEquals(413, response.getStatusLine().getStatusCode()); @@ -336,7 +336,7 @@ public void should200OnPOSTWithAuthorizationHeaderExplicitHandlerSetting() throw public void should200OnPOSTWithGremlinQueryStringArgumentWithBindingsAndFunction() throws Exception { final CloseableHttpClient httpclient = HttpClients.createDefault(); final HttpPost httppost = new HttpPost(TestClientFactory.createURLString()); - httppost.setEntity(new StringEntity("{\"gremlin\":\"addItUp(Integer.parseInt(x),Integer.parseInt(y))\",\"language\":\"gremlin-groovy\",\"bindings\":\"[x:\\\"10\\\",y:\\\"10\\\"]\"}", Consts.UTF_8)); + httppost.setEntity(new StringEntity("{\"gremlin\":\"addItUp(Integer.parseInt(x),Integer.parseInt(y))\",\"language\":\"gremlin-groovy\",\"parameters\":\"[x:\\\"10\\\",y:\\\"10\\\"]\"}", Consts.UTF_8)); try (final CloseableHttpResponse response = httpclient.execute(httppost)) { assertEquals(200, response.getStatusLine().getStatusCode()); @@ -664,7 +664,7 @@ public void should200OnPOSTWithGremlinJsonEndcodedBodyAndBindings() throws Excep final CloseableHttpClient httpclient = HttpClients.createDefault(); final HttpPost httppost = new HttpPost(TestClientFactory.createURLString()); httppost.addHeader("Content-Type", "application/json"); - httppost.setEntity(new StringEntity("{\"gremlin\":\"x+y\", \"bindings\":\"[x:10,y:10]\", \"language\":\"gremlin-groovy\"}", Consts.UTF_8)); + httppost.setEntity(new StringEntity("{\"gremlin\":\"x+y\", \"parameters\":\"[x:10,y:10]\", \"language\":\"gremlin-groovy\"}", Consts.UTF_8)); try (final CloseableHttpResponse response = httpclient.execute(httppost)) { assertEquals(200, response.getStatusLine().getStatusCode()); @@ -680,7 +680,7 @@ public void should200OnPOSTWithGremlinJsonEndcodedBodyAndLongBindings() throws E final CloseableHttpClient httpclient = HttpClients.createDefault(); final HttpPost httppost = new HttpPost(TestClientFactory.createURLString()); httppost.addHeader("Content-Type", "application/json"); - httppost.setEntity(new StringEntity("{\"gremlin\":\"g.inject(x)\", \"bindings\":\"[x:10]\", \"language\":\"gremlin-groovy\"}", Consts.UTF_8)); + httppost.setEntity(new StringEntity("{\"gremlin\":\"g.inject(x)\", \"parameters\":\"[x:10]\", \"language\":\"gremlin-groovy\"}", Consts.UTF_8)); try (final CloseableHttpResponse response = httpclient.execute(httppost)) { assertEquals(200, response.getStatusLine().getStatusCode()); @@ -696,7 +696,7 @@ public void should200OnPOSTWithGremlinJsonEndcodedBodyAndDoubleBindings() throws final CloseableHttpClient httpclient = HttpClients.createDefault(); final HttpPost httppost = new HttpPost(TestClientFactory.createURLString()); httppost.addHeader("Content-Type", "application/json"); - httppost.setEntity(new StringEntity("{\"gremlin\":\"g.inject(x)\", \"bindings\":\"[x:10.5]\", \"language\":\"gremlin-groovy\"}", Consts.UTF_8)); + httppost.setEntity(new StringEntity("{\"gremlin\":\"g.inject(x)\", \"parameters\":\"[x:10.5]\", \"language\":\"gremlin-groovy\"}", Consts.UTF_8)); try (final CloseableHttpResponse response = httpclient.execute(httppost)) { assertEquals(200, response.getStatusLine().getStatusCode()); @@ -712,7 +712,7 @@ public void should200OnPOSTWithGremlinJsonEndcodedBodyAndStringBindings() throws final CloseableHttpClient httpclient = HttpClients.createDefault(); final HttpPost httppost = new HttpPost(TestClientFactory.createURLString()); httppost.addHeader("Content-Type", "application/json"); - httppost.setEntity(new StringEntity("{\"gremlin\":\"g.V(1).out(x).values('name')\", \"bindings\":\"[x:\\\"knows\\\"]\", \"g\":\"gmodern\"}", Consts.UTF_8)); + httppost.setEntity(new StringEntity("{\"gremlin\":\"g.V(1).out(x).values('name')\", \"parameters\":\"[x:\\\"knows\\\"]\", \"g\":\"gmodern\"}", Consts.UTF_8)); try (final CloseableHttpResponse response = httpclient.execute(httppost)) { assertEquals(200, response.getStatusLine().getStatusCode()); @@ -728,7 +728,7 @@ public void should200OnPOSTWithGremlinJsonEndcodedBodyAndBooleanBindings() throw final CloseableHttpClient httpclient = HttpClients.createDefault(); final HttpPost httppost = new HttpPost(TestClientFactory.createURLString()); httppost.addHeader("Content-Type", "application/json"); - httppost.setEntity(new StringEntity("{\"gremlin\":\"g.inject(x)\", \"bindings\":\"[x:true]\", \"language\":\"gremlin-groovy\"}", Consts.UTF_8)); + httppost.setEntity(new StringEntity("{\"gremlin\":\"g.inject(x)\", \"parameters\":\"[x:true]\", \"language\":\"gremlin-groovy\"}", Consts.UTF_8)); try (final CloseableHttpResponse response = httpclient.execute(httppost)) { assertEquals(200, response.getStatusLine().getStatusCode()); @@ -744,7 +744,7 @@ public void should200OnPOSTWithGremlinJsonEndcodedBodyAndNullBindings() throws E final CloseableHttpClient httpclient = HttpClients.createDefault(); final HttpPost httppost = new HttpPost(TestClientFactory.createURLString()); httppost.addHeader("Content-Type", "application/json"); - httppost.setEntity(new StringEntity("{\"gremlin\":\"g.inject(x)\", \"bindings\":\"[x:null]\", \"language\":\"gremlin-groovy\"}", Consts.UTF_8)); + httppost.setEntity(new StringEntity("{\"gremlin\":\"g.inject(x)\", \"parameters\":\"[x:null]\", \"language\":\"gremlin-groovy\"}", Consts.UTF_8)); try (final CloseableHttpResponse response = httpclient.execute(httppost)) { assertEquals(200, response.getStatusLine().getStatusCode()); @@ -760,7 +760,7 @@ public void should200OnPOSTWithGremlinJsonEndcodedBodyAndArrayBindings() throws final CloseableHttpClient httpclient = HttpClients.createDefault(); final HttpPost httppost = new HttpPost(TestClientFactory.createURLString()); httppost.addHeader("Content-Type", "application/json"); - httppost.setEntity(new StringEntity("{\"gremlin\":\"g.inject(x).unfold()\", \"bindings\":\"[x:[1,2,3]]\", \"language\":\"gremlin-groovy\"}", Consts.UTF_8)); + httppost.setEntity(new StringEntity("{\"gremlin\":\"g.inject(x).unfold()\", \"parameters\":\"[x:[1,2,3]]\", \"language\":\"gremlin-groovy\"}", Consts.UTF_8)); try (final CloseableHttpResponse response = httpclient.execute(httppost)) { assertEquals(200, response.getStatusLine().getStatusCode()); @@ -779,7 +779,7 @@ public void should200OnPOSTWithGremlinJsonEndcodedBodyAndMapBindings() throws Ex final CloseableHttpClient httpclient = HttpClients.createDefault(); final HttpPost httppost = new HttpPost(TestClientFactory.createURLString()); httppost.addHeader("Content-Type", "application/json"); - httppost.setEntity(new StringEntity("{\"gremlin\":\"g.inject(x)\", \"bindings\":\"[x:[\\\"y\\\":1]]\", \"language\":\"gremlin-groovy\"}", Consts.UTF_8)); + httppost.setEntity(new StringEntity("{\"gremlin\":\"g.inject(x)\", \"parameters\":\"[x:[\\\"y\\\":1]]\", \"language\":\"gremlin-groovy\"}", Consts.UTF_8)); try (final CloseableHttpResponse response = httpclient.execute(httppost)) { assertEquals(200, response.getStatusLine().getStatusCode()); @@ -796,7 +796,7 @@ public void should400OnPOSTWithGremlinJsonEndcodedBodyAndBadBindings() throws Ex final CloseableHttpClient httpclient = HttpClients.createDefault(); final HttpPost httppost = new HttpPost(TestClientFactory.createURLString()); httppost.addHeader("Content-Type", "application/json"); - httppost.setEntity(new StringEntity("{\"gremlin\":\"g.inject(x, y)\", \"bindings\":10}, \"language\":\"gremlin-groovy\"}", Consts.UTF_8)); + httppost.setEntity(new StringEntity("{\"gremlin\":\"g.inject(x, y)\", \"parameters\":10}, \"language\":\"gremlin-groovy\"}", Consts.UTF_8)); try (final CloseableHttpResponse response = httpclient.execute(httppost)) { assertEquals(400, response.getStatusLine().getStatusCode()); @@ -1218,7 +1218,7 @@ public void should200OnPOSTWithGremlinGraphSONEndcodedBodyAndDoubleBindings() th final SimpleBindings bindings = new SimpleBindings(); bindings.put("x", 10.5d); final ByteBuf serializedRequest = serializer.serializeRequestAsBinary( - RequestMessage.build("g.inject(x)").addBindings(bindings).addLanguage("gremlin-groovy").create(), + RequestMessage.build("g.inject(x)").addParameters(bindings).addLanguage("gremlin-groovy").create(), new UnpooledByteBufAllocator(false)); final CloseableHttpClient httpclient = HttpClients.createDefault(); @@ -1240,7 +1240,7 @@ public void should200OnPOSTWithGremlinGraphSONEndcodedBodyAndDoubleBindings() th public void should400OnPOSTWithInvalidRequestArgsWhenInvalidBindingsSupplied() throws Exception { final GraphSONMessageSerializerV4 serializer = new GraphSONMessageSerializerV4(); final ByteBuf serializedRequest = serializer.serializeRequestAsBinary( - RequestMessage.build("g.V(id)").addBindings("[id:1]").addLanguage("gremlin-groovy").create(), + RequestMessage.build("g.V(id)").addParameters("[id:1]").addLanguage("gremlin-groovy").create(), new UnpooledByteBufAllocator(false)); final CloseableHttpClient httpclient = HttpClients.createDefault(); diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java index 07e8e4ce717..56e04a3c268 100644 --- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java +++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java @@ -531,7 +531,7 @@ public void shouldReturnInvalidRequestArgsWhenInvalidReservedBindingKeyIsUsed() final Map bindings = new HashMap<>(); bindings.put(T.id.getAccessor(), "123"); final RequestMessage request = RequestMessage.build("g.inject(1,2,3,4,5,6,7,8,9,0)") - .addBindings(bindings).create(); + .addParameters(bindings).create(); final CountDownLatch latch = new CountDownLatch(1); final AtomicBoolean pass = new AtomicBoolean(false); client.submit(request, result -> { @@ -550,7 +550,7 @@ public void shouldReturnInvalidRequestArgsWhenInvalidReservedBindingKeyIsUsed() final Map bindings = new HashMap<>(); bindings.put("id", "123"); // "id" is invalid for gremlin-groovy, but not gremlin-lang final RequestMessage request = RequestMessage.build("g.inject(1,2,3,4,5,6,7,8,9,0)") - .addBindings(bindings).addLanguage("gremlin-groovy").create(); + .addParameters(bindings).addLanguage("gremlin-groovy").create(); final CountDownLatch latch = new CountDownLatch(1); final AtomicBoolean pass = new AtomicBoolean(false); client.submit(request, result -> { @@ -573,7 +573,7 @@ public void shouldReturnInvalidRequestArgsWhenBindingCountExceedsAllowable() thr bindings.put("x", 1); bindings.put("y", "knows"); final RequestMessage request = RequestMessage.build("g.V(x).out(y).values('name')") - .addBindings(bindings).addG("gmodern").create(); + .addParameters(bindings).addG("gmodern").create(); final CountDownLatch latch = new CountDownLatch(1); final AtomicBoolean pass = new AtomicBoolean(false); client.submit(request, result -> { @@ -592,7 +592,7 @@ public void shouldReturnInvalidRequestArgsWhenBindingCountExceedsAllowable() thr final Map bindings = new HashMap<>(); bindings.put("x", 1); final RequestMessage request = RequestMessage.build("g.V(x).out('knows').values('name')") - .addBindings(bindings).addG("gmodern").create(); + .addParameters(bindings).addG("gmodern").create(); final CountDownLatch latch = new CountDownLatch(1); final AtomicBoolean pass = new AtomicBoolean(false); client.submit(request, result -> { @@ -614,7 +614,7 @@ public void shouldReturnInvalidRequestArgsWhenInvalidNullBindingKeyIsUsed() thro final Map bindings = new HashMap<>(); bindings.put(null, "123"); final RequestMessage request = RequestMessage.build("g.inject(1,2,3,4,5,6,7,8,9,0)") - .addBindings(bindings).create(); + .addParameters(bindings).create(); final CountDownLatch latch = new CountDownLatch(1); final AtomicBoolean pass = new AtomicBoolean(false); client.submit(request, result -> { @@ -1150,7 +1150,7 @@ public void ensureScriptEngineDefaultsToGremlinLang() { public void shouldSubmitWithStringBindingsViaRequestMessage() throws Exception { try (SimpleClient client = TestClientFactory.createSimpleHttpClient()) { final RequestMessage request = RequestMessage.build("g.V(x).out(y).values('name')") - .addBindings("[\"x\":1,\"y\":\"knows\"]").addG("gmodern").create(); + .addParameters("[\"x\":1,\"y\":\"knows\"]").addG("gmodern").create(); final List responses = client.submit(request); assertEquals(HttpResponseStatus.OK, responses.get(0).getStatus().getCode()); assertEquals("vadas", responses.get(0).getResult().getData().get(0)); @@ -1161,7 +1161,7 @@ public void shouldSubmitWithStringBindingsViaRequestMessage() throws Exception { public void shouldRejectTraversalInjectionInStringBindings() throws Exception { try (SimpleClient client = TestClientFactory.createSimpleHttpClient()) { final RequestMessage request = RequestMessage.build("g.V(x)") - .addBindings("[x:__.V().drop()]").addG("gmodern").create(); + .addParameters("[x:__.V().drop()]").addG("gmodern").create(); final List responses = client.submit(request); assertEquals(HttpResponseStatus.BAD_REQUEST, responses.get(0).getStatus().getCode()); } diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSslIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSslIntegrateTest.java index 2e73cca38e5..a1b13c68983 100644 --- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSslIntegrateTest.java +++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSslIntegrateTest.java @@ -172,7 +172,7 @@ public void shouldEnableWebSocketSsl() throws Exception { bindings.put("x", 123); bindings.put("y", 123); final RequestMessage request = RequestMessage.build("x+y") - .addBindings(bindings).addLanguage("gremlin-groovy").create(); + .addParameters(bindings).addLanguage("gremlin-groovy").create(); final CountDownLatch latch = new CountDownLatch(1); final AtomicBoolean pass = new AtomicBoolean(false); client.submit(request, result -> { diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/handler/HttpRequestMessageDecoderTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/handler/HttpRequestMessageDecoderTest.java index 62045069bc1..52f8cdd4cc6 100644 --- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/handler/HttpRequestMessageDecoderTest.java +++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/handler/HttpRequestMessageDecoderTest.java @@ -147,7 +147,7 @@ public void shouldCorrectlyDeserializeGremlinFromPostRequestWithAllScriptFieldsS final String gremlin = "g.V(x)"; final ByteBuf buffer = allocator.buffer(); buffer.writeCharSequence("{ \"gremlin\": \"" + gremlin + - "\", \"bindings\":\"[\\\"x\\\":\\\"2\\\"]\"" + + "\", \"parameters\":\"[\\\"x\\\":\\\"2\\\"]\"" + ", \"language\": \"gremlin-groovy\"}", CharsetUtil.UTF_8); @@ -163,7 +163,7 @@ public void shouldCorrectlyDeserializeGremlinFromPostRequestWithAllScriptFieldsS final RequestMessage decodedRequestMessage = testChannel.readInbound(); assertEquals(gremlin, decodedRequestMessage.getGremlin()); assertEquals("gremlin-groovy", decodedRequestMessage.getField(Tokens.ARGS_LANGUAGE)); - assertEquals("[\"x\":\"2\"]", decodedRequestMessage.getField(Tokens.ARGS_BINDINGS)); + assertEquals("[\"x\":\"2\"]", decodedRequestMessage.getField(Tokens.ARGS_PARAMETERS)); } @Test @@ -314,7 +314,7 @@ public void shouldAddValidFieldsToRequestMessage() throws SerializationException final UUID rid = UUID.randomUUID(); final ByteBuf buffer = allocator.buffer(); buffer.writeCharSequence("{\"gremlin\":\"g.V().limit(2)\",\"batchSize\":\"10\",\"language\":\"gremlin-lang\"," + - "\"g\":\"gmodern\",\"bindings\":\"[\\\"x\\\":1]\",\"timeoutMs\":\"12\"," + + "\"g\":\"gmodern\",\"parameters\":\"[\\\"x\\\":1]\",\"timeoutMs\":\"12\"," + "\"materializeProperties\":\"" + Tokens.MATERIALIZE_PROPERTIES_TOKENS + "\"}", CharsetUtil.UTF_8); final HttpHeaders headers = new DefaultHttpHeaders(); @@ -331,7 +331,7 @@ public void shouldAddValidFieldsToRequestMessage() throws SerializationException assertEquals(10, (int) decodedRequest.getField(Tokens.ARGS_BATCH_SIZE)); assertEquals("gremlin-lang", decodedRequest.getField(Tokens.ARGS_LANGUAGE)); assertEquals("gmodern", decodedRequest.getField(Tokens.ARGS_G)); - assertEquals("[\"x\":1]", decodedRequest.getField(Tokens.ARGS_BINDINGS)); + assertEquals("[\"x\":1]", decodedRequest.getField(Tokens.ARGS_PARAMETERS)); assertEquals(12, (long) decodedRequest.getField(Tokens.TIMEOUT_MS)); assertEquals(Tokens.MATERIALIZE_PROPERTIES_TOKENS, decodedRequest.getField(Tokens.ARGS_MATERIALIZE_PROPERTIES)); } diff --git a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/Tokens.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/Tokens.java index 2668b8c66df..8654e3dad02 100644 --- a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/Tokens.java +++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/Tokens.java @@ -47,10 +47,10 @@ public static final class Headers { public static final String ARGS_BATCH_SIZE = "batchSize"; /** - * Argument name that allows to provide a map of key/value pairs to apply as variables in the context of + * Argument name that allows to provide a map of key/value pairs to apply as query parameters in the context of * the Gremlin request sent to the server. */ - public static final String ARGS_BINDINGS = "bindings"; + public static final String ARGS_PARAMETERS = "parameters"; /** * Argument name that allows definition of alias names for {@link Graph} and {@link TraversalSource} objects on diff --git a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/message/RequestMessage.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/message/RequestMessage.java index a08c4abada7..5b974926f2d 100644 --- a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/message/RequestMessage.java +++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/message/RequestMessage.java @@ -125,23 +125,23 @@ public Builder addLanguage(final String language) { } /** - * Sets the bindings as a gremlin-lang map literal string. Calling this method multiple - * times will replace the previous bindings (last-one-wins). + * Sets the query parameters as a gremlin-lang map literal string. Calling this method multiple + * times will replace the previous parameters (last-one-wins). */ - public Builder addBindings(final String bindingsString) { - Objects.requireNonNull(bindingsString, "bindings argument cannot be null."); - this.fields.put(Tokens.ARGS_BINDINGS, bindingsString); + public Builder addParameters(final String parametersString) { + Objects.requireNonNull(parametersString, "parameters argument cannot be null."); + this.fields.put(Tokens.ARGS_PARAMETERS, parametersString); return this; } /** - * Sets the bindings from a map by converting it to a gremlin-lang map literal string + * Sets the query parameters from a map by converting it to a gremlin-lang map literal string * using {@link GremlinLang#convertParametersToString(Map)}. Calling this method multiple - * times will replace the previous bindings (last-one-wins). + * times will replace the previous parameters (last-one-wins). */ - public Builder addBindings(final Map otherBindings) { - Objects.requireNonNull(otherBindings, "bindings argument cannot be null."); - this.fields.put(Tokens.ARGS_BINDINGS, GremlinLang.convertParametersToString(otherBindings)); + public Builder addParameters(final Map otherParameters) { + Objects.requireNonNull(otherParameters, "parameters argument cannot be null."); + this.fields.put(Tokens.ARGS_PARAMETERS, GremlinLang.convertParametersToString(otherParameters)); return this; } diff --git a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/AbstractGraphSONMessageSerializerV4.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/AbstractGraphSONMessageSerializerV4.java index 22e580086a3..d14168c216e 100644 --- a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/AbstractGraphSONMessageSerializerV4.java +++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/AbstractGraphSONMessageSerializerV4.java @@ -324,8 +324,8 @@ public RequestMessage createObject(final Map data) { if (data.containsKey(SerTokens.TOKEN_G)) { builder.addG(data.get(SerTokens.TOKEN_G).toString()); } - if (data.containsKey(SerTokens.TOKEN_BINDINGS)) { - builder.addBindings(data.get(SerTokens.TOKEN_BINDINGS).toString()); + if (data.containsKey(SerTokens.TOKEN_PARAMETERS)) { + builder.addParameters(data.get(SerTokens.TOKEN_PARAMETERS).toString()); } if (data.containsKey(Tokens.TIMEOUT_MS)) { // Can be int for untyped JSON and long for typed GraphSON. diff --git a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/SerTokens.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/SerTokens.java index 34243c29e09..69a32cc88f5 100644 --- a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/SerTokens.java +++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/SerTokens.java @@ -32,7 +32,7 @@ private SerTokens() {} public static final String TOKEN_MESSAGE = "message"; public static final String TOKEN_GREMLIN = "gremlin"; public static final String TOKEN_LANGUAGE = "language"; - public static final String TOKEN_BINDINGS = "bindings"; + public static final String TOKEN_PARAMETERS = "parameters"; public static final String TOKEN_G = "g"; public static final String TOKEN_TIMEOUT_MS = "timeoutMs"; public static final String TOKEN_MATERIALIZE_PROPERTIES = "materializeProperties"; diff --git a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/binary/RequestMessageSerializer.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/binary/RequestMessageSerializer.java index 2f30d43b1df..6b523dd5f8f 100644 --- a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/binary/RequestMessageSerializer.java +++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/binary/RequestMessageSerializer.java @@ -58,8 +58,8 @@ public RequestMessage readValue(final ByteBuf byteBuf, final GraphBinaryReader c if (fields.containsKey(SerTokens.TOKEN_G)) { builder.addG(fields.get(SerTokens.TOKEN_G).toString()); } - if (fields.containsKey(SerTokens.TOKEN_BINDINGS)) { - builder.addBindings(fields.get(SerTokens.TOKEN_BINDINGS).toString()); + if (fields.containsKey(SerTokens.TOKEN_PARAMETERS)) { + builder.addParameters(fields.get(SerTokens.TOKEN_PARAMETERS).toString()); } if (fields.containsKey(Tokens.TIMEOUT_MS)) { builder.addTimeoutMillis(((Number) fields.get(Tokens.TIMEOUT_MS)).longValue()); diff --git a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/structure/io/AbstractCompatibilityTest.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/structure/io/AbstractCompatibilityTest.java index 01837126145..f4363c208df 100644 --- a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/structure/io/AbstractCompatibilityTest.java +++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/structure/io/AbstractCompatibilityTest.java @@ -138,14 +138,14 @@ protected static void assertRequestMessage(final RequestMessage resource, final final RequestMessage recycled) { // Check per field rather than map equals since a new field may get added later. assertEquals(resource.getGremlin(), recycled.getGremlin()); - assertEquals(resource.getField(SerTokens.TOKEN_BINDINGS), recycled.getField(SerTokens.TOKEN_BINDINGS)); + assertEquals(resource.getField(SerTokens.TOKEN_PARAMETERS), recycled.getField(SerTokens.TOKEN_PARAMETERS)); assertEquals(resource.getField(SerTokens.TOKEN_LANGUAGE), recycled.getField(SerTokens.TOKEN_LANGUAGE)); assertEquals(resource.getField(SerTokens.TOKEN_G), recycled.getField(SerTokens.TOKEN_G)); assertEquals(resource.getField(SerTokens.TOKEN_TIMEOUT_MS), recycled.getField(SerTokens.TOKEN_TIMEOUT_MS)); assertEquals(resource.getField(SerTokens.TOKEN_MATERIALIZE_PROPERTIES), recycled.getField(SerTokens.TOKEN_MATERIALIZE_PROPERTIES)); assertEquals(resource.getGremlin(), fromStatic.getGremlin()); - assertEquals(resource.getField(SerTokens.TOKEN_BINDINGS), fromStatic.getField(SerTokens.TOKEN_BINDINGS)); + assertEquals(resource.getField(SerTokens.TOKEN_PARAMETERS), fromStatic.getField(SerTokens.TOKEN_PARAMETERS)); assertEquals(resource.getField(SerTokens.TOKEN_LANGUAGE), fromStatic.getField(SerTokens.TOKEN_LANGUAGE)); assertEquals(resource.getField(SerTokens.TOKEN_G), fromStatic.getField(SerTokens.TOKEN_G)); assertEquals(resource.getField(SerTokens.TOKEN_TIMEOUT_MS), fromStatic.getField(SerTokens.TOKEN_TIMEOUT_MS)); diff --git a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/message/RequestMessageTest.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/message/RequestMessageTest.java index 13376778a8d..77a67b14b3d 100644 --- a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/message/RequestMessageTest.java +++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/message/RequestMessageTest.java @@ -38,47 +38,47 @@ public void shouldSetScriptGremlin() { } @Test - public void shouldSetBindingsWithMap() { - final Map bindings = new HashMap<>(); - bindings.put("a", "b"); - bindings.put("g", "gmodern"); - final RequestMessage msg = RequestMessage.build("gremlin").addBindings(bindings).create(); - // bindings are now stored as a gremlin-lang map literal string - final String bindingsString = msg.getField(Tokens.ARGS_BINDINGS); - assertTrue(bindingsString.startsWith("[")); - assertTrue(bindingsString.endsWith("]")); - assertTrue(bindingsString.contains("\"a\":\"b\"")); - assertTrue(bindingsString.contains("\"g\":\"gmodern\"")); + public void shouldSetParametersWithMap() { + final Map parameters = new HashMap<>(); + parameters.put("a", "b"); + parameters.put("g", "gmodern"); + final RequestMessage msg = RequestMessage.build("gremlin").addParameters(parameters).create(); + // parameters are now stored as a gremlin-lang map literal string + final String parametersString = msg.getField(Tokens.ARGS_PARAMETERS); + assertTrue(parametersString.startsWith("[")); + assertTrue(parametersString.endsWith("]")); + assertTrue(parametersString.contains("\"a\":\"b\"")); + assertTrue(parametersString.contains("\"g\":\"gmodern\"")); } @Test - public void shouldSetBindingsWithString() { + public void shouldSetParametersWithString() { final RequestMessage msg = RequestMessage.build("gremlin") - .addBindings("[a:\"b\",g:\"gmodern\"]") + .addParameters("[a:\"b\",g:\"gmodern\"]") .create(); - assertEquals("[a:\"b\",g:\"gmodern\"]", msg.getField(Tokens.ARGS_BINDINGS)); + assertEquals("[a:\"b\",g:\"gmodern\"]", msg.getField(Tokens.ARGS_PARAMETERS)); } @Test - public void shouldNotContainBindingsWhenNoneSet() { + public void shouldNotContainParametersWhenNoneSet() { final RequestMessage msg = RequestMessage.build("g.V()").create(); - assertNull(msg.getField(Tokens.ARGS_BINDINGS)); + assertNull(msg.getField(Tokens.ARGS_PARAMETERS)); } @Test - public void shouldOverwriteBindingsOnMultipleCalls() { + public void shouldOverwriteParametersOnMultipleCalls() { final RequestMessage msg = RequestMessage.build("gremlin") - .addBindings("[x:1]") - .addBindings("[y:2]") + .addParameters("[x:1]") + .addParameters("[y:2]") .create(); - assertEquals("[y:2]", msg.getField(Tokens.ARGS_BINDINGS)); + assertEquals("[y:2]", msg.getField(Tokens.ARGS_PARAMETERS)); } @Test(expected = IllegalArgumentException.class) - public void shouldRejectUnsupportedTypeInBindingsMap() { - final Map bindings = new HashMap<>(); - bindings.put("x", new Thread()); - RequestMessage.build("g.V()").addBindings(bindings); + public void shouldRejectUnsupportedTypeInParametersMap() { + final Map parameters = new HashMap<>(); + parameters.put("x", new Thread()); + RequestMessage.build("g.V()").addParameters(parameters); } @Test @@ -126,18 +126,18 @@ public void shouldGetFields() { final String g = "gmodern"; final String lang = "lang"; final String query = "g.V()"; - final Map bindings = new HashMap<>(); - bindings.put("b", "c"); - bindings.put("g", "gmodern"); + final Map parameters = new HashMap<>(); + parameters.put("b", "c"); + parameters.put("g", "gmodern"); - final RequestMessage msg = RequestMessage.build(query).addG(g).addBindings(bindings).addLanguage(lang).create(); + final RequestMessage msg = RequestMessage.build(query).addG(g).addParameters(parameters).addLanguage(lang).create(); final Map fields = msg.getFields(); assertEquals(g, fields.get(Tokens.ARGS_G)); assertEquals(lang, fields.get(Tokens.ARGS_LANGUAGE)); - // bindings are now a gremlin-lang string, not the original map - final String bindingsString = (String) fields.get(Tokens.ARGS_BINDINGS); - assertTrue(bindingsString.contains("\"b\":\"c\"")); - assertTrue(bindingsString.contains("\"g\":\"gmodern\"")); + // parameters are now a gremlin-lang string, not the original map + final String parametersString = (String) fields.get(Tokens.ARGS_PARAMETERS); + assertTrue(parametersString.contains("\"b\":\"c\"")); + assertTrue(parametersString.contains("\"g\":\"gmodern\"")); assertEquals(query, msg.getGremlin()); } diff --git a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/MessageSerializerTest.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/MessageSerializerTest.java index e8874bf5026..e38ed20f01e 100644 --- a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/MessageSerializerTest.java +++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/MessageSerializerTest.java @@ -81,7 +81,7 @@ public void shouldSerializeAndDeserializeRequest() throws SerializationException .addTimeoutMillis(500) .addG("g1") .addLanguage("some-lang") - .addBindings("['k':'v']") + .addParameters("['k':'v']") .create(); final ByteBuf buffer = serializer.serializeRequestAsBinary(request, allocator);