This is an automated email from the ASF dual-hosted git repository. kenhuuu pushed a commit to branch bindings-to-params in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 0464df356a5442c43f93921a9bd7ca72a0b44fba Author: Ken Hu <[email protected]> AuthorDate: Wed Jul 1 17:29:03 2026 -0700 TINKERPOP-3262 Rename request "bindings" field to "parameters" Standardize on "parameter" for the gremlin-lang query parameter map across the wire (JSON/GraphBinary/GraphSON), server internals and error messages, and the public driver APIs of all five GLVs. Bounded to that one concept. "binding" is kept where it names something else, since renaming those would be wrong rather than churn: javax.script.Bindings and its ecosystem (BindingsCustomizer, script-engine and global TraversalSource bindings), where the server still hands parameters to a javax.script.Bindings for evaluation as a boundary with a foreign API; GQL pattern-match bindings in gql-gremlin; the gremlin-lang grammar's "variable" vocabulary (VariableResolver); and gremlin-core's step Parameters, disambiguated in docs as "step parameters". Assisted-by: Claude Code:claude-opus-4-8 --- CHANGELOG.asciidoc | 1 + docs/src/dev/provider/index.asciidoc | 6 +- docs/src/reference/gremlin-applications.asciidoc | 21 +++---- docs/src/reference/gremlin-variants.asciidoc | 6 +- docs/src/upgrade/release-4.x.x.asciidoc | 30 ++++++++++ .../Gremlin.Net/Driver/GremlinClientExtensions.cs | 26 ++++----- .../Gremlin.Net/Driver/Messages/RequestMessage.cs | 60 +++++++++---------- .../Driver/Remote/DriverRemoteConnection.cs | 2 +- .../Driver/Remote/TransactionRemoteConnection.cs | 2 +- gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs | 4 +- .../MessageSerializerBenchmarks.cs | 2 +- .../Docs/Reference/GremlinApplicationsTests.cs | 4 +- .../Driver/GremlinClientTests.cs | 2 +- .../Driver/DriverRemoteConnectionTests.cs | 6 +- .../Driver/HttpRequestContextTests.cs | 6 +- .../Driver/Messages/RequestMessageTests.cs | 30 +++++----- .../apache/tinkerpop/gremlin/driver/Client.java | 2 +- gremlin-go/driver/client.go | 20 +++---- gremlin-go/driver/client_test.go | 12 ++-- gremlin-go/driver/gremlinlang_test.go | 4 +- gremlin-go/driver/request.go | 6 +- gremlin-go/driver/requestOptions.go | 44 +++++++------- gremlin-go/driver/requestOptions_test.go | 48 +++++++-------- gremlin-go/driver/request_test.go | 32 +++++----- gremlin-js/gremlin-javascript/lib/driver/client.ts | 32 +++++----- .../lib/driver/driver-remote-connection.ts | 2 +- .../lib/driver/request-message.ts | 68 +++++++++++----------- .../gremlin-javascript/lib/process/transaction.ts | 4 +- .../io/binary/internals/GraphBinaryWriter.js | 6 +- .../test/integration/client-tests.js | 2 +- .../main/python/gremlin_python/driver/client.py | 33 +++++------ .../driver/driver_remote_connection.py | 6 +- .../main/python/gremlin_python/driver/request.py | 2 +- .../python/gremlin_python/driver/transaction.py | 4 +- .../python/tests/integration/driver/test_client.py | 30 +++++----- .../server/handler/HttpGremlinEndpointHandler.java | 46 +++++++-------- .../server/handler/HttpRequestMessageDecoder.java | 4 +- .../gremlin/server/util/GremlinError.java | 14 ++--- .../server/GremlinServerHttpIntegrateTest.java | 26 ++++----- .../gremlin/server/GremlinServerIntegrateTest.java | 14 ++--- .../server/GremlinServerSslIntegrateTest.java | 2 +- .../handler/HttpRequestMessageDecoderTest.java | 8 +-- .../org/apache/tinkerpop/gremlin/util/Tokens.java | 4 +- .../gremlin/util/message/RequestMessage.java | 20 +++---- .../ser/AbstractGraphSONMessageSerializerV4.java | 4 +- .../tinkerpop/gremlin/util/ser/SerTokens.java | 2 +- .../util/ser/binary/RequestMessageSerializer.java | 4 +- .../structure/io/AbstractCompatibilityTest.java | 4 +- .../gremlin/util/message/RequestMessageTest.java | 64 ++++++++++---------- .../util/ser/binary/MessageSerializerTest.java | 2 +- 50 files changed, 403 insertions(+), 380 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index b1456d0ec1..b593012be6 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -123,6 +123,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<String, Object>` 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/provider/index.asciidoc b/docs/src/dev/provider/index.asciidoc index ec642cbfa1..0af780e14d 100644 --- a/docs/src/dev/provider/index.asciidoc +++ b/docs/src/dev/provider/index.asciidoc @@ -1198,7 +1198,7 @@ Gremlin-Hints: <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 eaa9950b69..32917a469b 100644 --- a/docs/src/reference/gremlin-applications.asciidoc +++ b/docs/src/reference/gremlin-applications.asciidoc @@ -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 941e2e83dd..3badac7101 100644 --- a/docs/src/reference/gremlin-variants.asciidoc +++ b/docs/src/reference/gremlin-variants.asciidoc @@ -492,14 +492,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] @@ -2256,7 +2256,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 a6040deba5..a02b85fb18 100644 --- a/docs/src/upgrade/release-4.x.x.asciidoc +++ b/docs/src/upgrade/release-4.x.x.asciidoc @@ -32,6 +32,36 @@ complete list of all the modifications that are part of this release. === Upgrading for Users +==== Bindings are now Parameters + +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<String, Object> 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 .NET Connection Options TinkerPop 4.x standardizes connection option names and defaults across the GLVs. In `gremlin-dotnet`, several diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClientExtensions.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClientExtensions.cs index 66927c5b17..da13259bb2 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 { /// <summary> - /// 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. /// </summary> /// <remarks> @@ -44,7 +44,7 @@ namespace Gremlin.Net.Driver /// <typeparam name="T">The type of the expected result.</typeparam> /// <param name="gremlinClient">The <see cref="IGremlinClient" /> that submits the request.</param> /// <param name="requestScript">The Gremlin request script to send.</param> - /// <param name="bindings">Bindings for parameters used in the requestScript.</param> + /// <param name="parameters">Parameters used in the requestScript.</param> /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param> /// <returns>A single result received from the Gremlin Server.</returns> /// <exception cref="Exceptions.ResponseException"> @@ -53,10 +53,10 @@ namespace Gremlin.Net.Driver /// </exception> public static async Task<T?> SubmitWithSingleResultAsync<T>(this IGremlinClient gremlinClient, string requestScript, - Dictionary<string, object>? bindings = null, + Dictionary<string, object>? parameters = null, CancellationToken cancellationToken = default) { - await using var resultSet = await gremlinClient.SubmitAsync<T>(requestScript, bindings, cancellationToken) + await using var resultSet = await gremlinClient.SubmitAsync<T>(requestScript, parameters, cancellationToken) .ConfigureAwait(false); await foreach (var item in resultSet.WithCancellation(cancellationToken).ConfigureAwait(false)) { @@ -94,12 +94,12 @@ namespace Gremlin.Net.Driver } /// <summary> - /// 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. /// </summary> /// <param name="gremlinClient">The <see cref="IGremlinClient" /> that submits the request.</param> /// <param name="requestScript">The Gremlin request script to send.</param> - /// <param name="bindings">Bindings for parameters used in the requestScript.</param> + /// <param name="parameters">Parameters used in the requestScript.</param> /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param> /// <returns>The task object representing the asynchronous operation.</returns> /// <exception cref="Exceptions.ResponseException"> @@ -107,9 +107,9 @@ namespace Gremlin.Net.Driver /// that an error occurred. /// </exception> public static async Task SubmitAsync(this IGremlinClient gremlinClient, string requestScript, - Dictionary<string, object>? bindings = null, CancellationToken cancellationToken = default) + Dictionary<string, object>? parameters = null, CancellationToken cancellationToken = default) { - await using var resultSet = await gremlinClient.SubmitAsync<object>(requestScript, bindings, cancellationToken).ConfigureAwait(false); + await using var resultSet = await gremlinClient.SubmitAsync<object>(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 @@ namespace Gremlin.Net.Driver } /// <summary> - /// 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. /// </summary> /// <typeparam name="T">The type of the expected results.</typeparam> /// <param name="gremlinClient">The <see cref="IGremlinClient" /> that submits the request.</param> /// <param name="requestScript">The Gremlin request script to send.</param> - /// <param name="bindings">Bindings for parameters used in the requestScript.</param> + /// <param name="parameters">Parameters used in the requestScript.</param> /// <param name="cancellationToken">The token to cancel the operation. The default value is None.</param> /// <returns>A <see cref="ResultSet{T}"/> containing the data and status attributes returned from the server.</returns> /// <exception cref="Exceptions.ResponseException"> @@ -153,12 +153,12 @@ namespace Gremlin.Net.Driver /// </exception> public static async Task<ResultSet<T>> SubmitAsync<T>(this IGremlinClient gremlinClient, string requestScript, - Dictionary<string, object>? bindings = null, + Dictionary<string, object>? 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<T>(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 e843f43d9e..c301adb701 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 @@ namespace Gremlin.Net.Driver.Messages public string Gremlin { get; } /// <summary> - /// Gets the fields map containing language, g, bindings, and other options. + /// Gets the fields map containing language, g, parameters, and other options. /// </summary> public Dictionary<string, object> Fields { get; } @@ -84,8 +84,8 @@ namespace Gremlin.Net.Driver.Messages { private readonly string _gremlin; private readonly Dictionary<string, object> _fields = new Dictionary<string, object>(); - private readonly Dictionary<string, object> _bindings = new Dictionary<string, object>(); - private string? _bindingsString; + private readonly Dictionary<string, object> _parameters = new Dictionary<string, object>(); + private string? _parametersString; internal Builder(string gremlin) { @@ -104,48 +104,48 @@ namespace Gremlin.Net.Driver.Messages } /// <summary> - /// Adds a single binding parameter. + /// Adds a single query parameter. /// </summary> - /// <param name="key">The binding key.</param> - /// <param name="val">The binding value.</param> + /// <param name="key">The parameter key.</param> + /// <param name="val">The parameter value.</param> /// <returns>The <see cref="Builder" />.</returns> - 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; } /// <summary> - /// 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 <see cref="AddBindingsString"/>. + /// Cannot be mixed with <see cref="AddParametersString"/>. /// </summary> - /// <param name="bindings">The bindings to add.</param> + /// <param name="parameters">The parameters to add.</param> /// <returns>The <see cref="Builder" />.</returns> - public Builder AddBindings(Dictionary<string, object> bindings) + public Builder AddParameters(Dictionary<string, object> 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; } /// <summary> - /// Sets the bindings as a pre-serialized gremlin-lang map literal string. - /// Cannot be mixed with <see cref="AddBinding"/> or <see cref="AddBindings"/>. + /// Sets the query parameters as a pre-serialized gremlin-lang map literal string. + /// Cannot be mixed with <see cref="AddParameter"/> or <see cref="AddParameters"/>. /// </summary> - /// <param name="bindingsString">The gremlin-lang bindings string.</param> + /// <param name="parametersString">The gremlin-lang parameters string.</param> /// <returns>The <see cref="Builder" />.</returns> - 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 @@ namespace Gremlin.Net.Driver.Messages /// <returns>The built <see cref="RequestMessage" />.</returns> 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 3112bf783c..15a7fefbad 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 @@ namespace Gremlin.Net.Driver.Remote 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 d63ec834f7..404f4ffe00 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 @@ namespace Gremlin.Net.Driver.Remote 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 7f39308ec0..0f57f87380 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs @@ -47,10 +47,10 @@ namespace Gremlin.Net.Driver public const string ArgsBatchSize = "batchSize"; /// <summary> - /// 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. /// </summary> - public const string ArgsBindings = "bindings"; + public const string ArgsParameters = "parameters"; /// <summary> /// 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 dfbf0082db..02510f68a9 100644 --- a/gremlin-dotnet/test/Gremlin.Net.Benchmarks/MessageSerializerBenchmarks.cs +++ b/gremlin-dotnet/test/Gremlin.Net.Benchmarks/MessageSerializerBenchmarks.cs @@ -66,7 +66,7 @@ namespace Gremlin.Net.Benchmarks 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 6851e8aa66..29954c8090 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 @@ namespace Gremlin.Net.IntegrationTest.Docs.Reference var gremlinServer = new GremlinServer("localhost", 8182); using (var gremlinClient = new GremlinClient(gremlinServer)) { - var bindings = new Dictionary<string, object> + var parameters = new Dictionary<string, object> { {"name", "marko"} }; var response = await gremlinClient.SubmitWithSingleResultAsync<object>("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 6370a5bb18..885bafccd8 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 @@ namespace Gremlin.Net.IntegrationTest.Driver } [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 e7ea25f648..fd489fcf92 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 @@ namespace Gremlin.Net.UnitTest.Driver } [Fact] - public async Task ShouldBuildRequestWithBindings() + public async Task ShouldBuildRequestWithParameters() { RequestMessage? capturedRequest = null; var client = CreateCapturingClient(msg => capturedRequest = msg); @@ -116,8 +116,8 @@ namespace Gremlin.Net.UnitTest.Driver await connection.SubmitAsync<object, object>(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 1052202644..05bcf870f2 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 @@ namespace Gremlin.Net.UnitTest.Driver } [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<string, string>(), message); @@ -289,7 +289,7 @@ namespace Gremlin.Net.UnitTest.Driver 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 4d669841b5..29a6ac0ff4 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 @@ namespace Gremlin.Net.UnitTest.Driver.Messages } [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<string, object> { { "x", 1 }, { "name", "test" } }; + var parameters = new Dictionary<string, object> { { "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 @@ namespace Gremlin.Net.UnitTest.Driver.Messages } [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 a8b1b49ad6..00c1037cda 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 abstract class Client implements RequestSubmitter, RequestSubmitterAsync // 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 9bc7a1ae29..5ad37942b9 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 f2623fdb60..61249dab5a 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 fad4cf4aa4..53c67e0c80 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 ebf375d49b..402e816e09 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 53863276d9..b419d13c1a 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 851e4d02e1..f8e7213de1 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 f1752b0f6c..a738d627a6 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 fbb1ac4671..c8f31f5dd0 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<ResultSet>} */ - submit(message: string, bindings: any | null, requestOptions?: RequestOptions): Promise<any> { - return this._connection.submit(this.#buildRequest(message, bindings, requestOptions)); + submit(message: string, parameters: any | null, requestOptions?: RequestOptions): Promise<any> { + 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<any>} */ - async *stream(message: string, bindings: any | null, requestOptions?: RequestOptions): AsyncGenerator<any> { - return yield* this._connection.stream(this.#buildRequest(message, bindings, requestOptions)); + async *stream(message: string, parameters: any | null, requestOptions?: RequestOptions): AsyncGenerator<any> { + 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 78caf3bec8..06e2f8c649 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 c878309935..9f54375422 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', @@ -38,7 +38,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; @@ -48,7 +48,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, @@ -61,7 +61,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; @@ -80,8 +80,8 @@ export class RequestMessage { return this.timeoutMs; } - getBindings(): object | undefined { - return this.bindings; + getParameters(): object | undefined { + return this.parameters; } getG(): string | undefined { @@ -117,8 +117,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; @@ -148,8 +148,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; @@ -169,36 +169,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; } @@ -239,20 +239,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 57b77022b2..0ce8984227 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<any> { + async submit(gremlin: string, parameters?: any, requestOptions?: any): Promise<any> { 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<void> { 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 5a9cae0db8..d9a1d8f792 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 eaf7a738c6..dfa3af8e15 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 7cb073f696..6f39f59c6c 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 @@ class Client: 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 @@ class Client: 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 3c0f094569..e911720a3a 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 @@ class DriverRemoteConnection(RemoteConnection): 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 @@ class DriverRemoteConnection(RemoteConnection): 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 119c76c0a9..b596cfccb5 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 @@ __author__ = 'David M. Brown ([email protected])' 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 857f1a2e3d..d83ded122b 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 @@ class Transaction: 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 @@ class Transaction: 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 0981e7737b..6fecf104c4 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 test_client_deflate_compression_round_trip(): 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): @@ -269,22 +269,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-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 eed9428c1d..4540de7303 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<Requ */ public static final Meter writePausesMeter = MetricManager.INSTANCE.getMeter(name(GremlinServer.class, "channels", "write-pauses")); - protected static final Set<String> INVALID_BINDINGS_KEYS = new HashSet<>(); + protected static final Set<String> 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<Requ T.label.getAccessor().toUpperCase(), T.value.getAccessor().toUpperCase())); for (Column enumItem : Column.values()) { - INVALID_BINDINGS_KEYS.add(enumItem.name()); + INVALID_PARAMETERS_KEYS.add(enumItem.name()); } for (Order enumItem : Order.values()) { - INVALID_BINDINGS_KEYS.add(enumItem.name()); + INVALID_PARAMETERS_KEYS.add(enumItem.name()); } for (Operator enumItem : Operator.values()) { - INVALID_BINDINGS_KEYS.add(enumItem.name()); + INVALID_PARAMETERS_KEYS.add(enumItem.name()); } for (Scope enumItem : Scope.values()) { - INVALID_BINDINGS_KEYS.add(enumItem.name()); + INVALID_PARAMETERS_KEYS.add(enumItem.name()); } for (Pop enumItem : Pop.values()) { - INVALID_BINDINGS_KEYS.add(enumItem.name()); + INVALID_PARAMETERS_KEYS.add(enumItem.name()); } } @@ -199,9 +199,9 @@ public class HttpGremlinEndpointHandler extends SimpleChannelInboundHandler<Requ final FutureTask<Void> 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 class HttpGremlinEndpointHandler extends SimpleChannelInboundHandler<Requ throw new ProcessingException(GremlinError.scriptEngineNotAvailable(language)); } - // Guard against bad parameters while trying to parse string-based bindings into a Map<String, Object> - if (requestMessage.optionalField(Tokens.ARGS_BINDINGS).isPresent()) { - Map<String, Object> 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<String, Object> + if (requestMessage.optionalField(Tokens.ARGS_PARAMETERS).isPresent()) { + Map<String, Object> 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<String> badBindings = IteratorUtils.set(IteratorUtils.<String>filter( - bindings.keySet().iterator(), - INVALID_BINDINGS_KEYS::contains)); - if (!badBindings.isEmpty()) { - throw new ProcessingException(GremlinError.binding(badBindings)); + final Set<String> badParameters = IteratorUtils.set(IteratorUtils.<String>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 8a688b6d6b..a47683fbf5 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 @@ public class HttpRequestMessageDecoder extends MessageToMessageDecoder<FullHttpR 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 e0e74c26d0..301a26f5b9 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 class GremlinError { } // 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 class GremlinError { return new GremlinError(HttpResponseStatus.BAD_REQUEST, message, "InvalidRequestException"); } - public static GremlinError binding(final Set<String> badBindings) { + public static GremlinError parameter(final Set<String> 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 c67a0add0d..e381d6c46a 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 class GremlinServerHttpIntegrateTest extends AbstractGremlinServerIntegra 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 class GremlinServerHttpIntegrateTest extends AbstractGremlinServerIntegra 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 class GremlinServerHttpIntegrateTest extends AbstractGremlinServerIntegra 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 class GremlinServerHttpIntegrateTest extends AbstractGremlinServerIntegra 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 class GremlinServerHttpIntegrateTest extends AbstractGremlinServerIntegra 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 class GremlinServerHttpIntegrateTest extends AbstractGremlinServerIntegra 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 class GremlinServerHttpIntegrateTest extends AbstractGremlinServerIntegra 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 class GremlinServerHttpIntegrateTest extends AbstractGremlinServerIntegra 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 class GremlinServerHttpIntegrateTest extends AbstractGremlinServerIntegra 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 class GremlinServerHttpIntegrateTest extends AbstractGremlinServerIntegra 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 class GremlinServerHttpIntegrateTest extends AbstractGremlinServerIntegra 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 class GremlinServerHttpIntegrateTest extends AbstractGremlinServerIntegra 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 class GremlinServerHttpIntegrateTest extends AbstractGremlinServerIntegra 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 a67592c2da..7140fc5914 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 @@ -520,7 +520,7 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration final Map<String, Object> 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 -> { @@ -539,7 +539,7 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration final Map<String, Object> 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 -> { @@ -562,7 +562,7 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration 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 -> { @@ -581,7 +581,7 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration final Map<String, Object> 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 -> { @@ -603,7 +603,7 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration final Map<String, Object> 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 -> { @@ -1139,7 +1139,7 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration 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<ResponseMessage> responses = client.submit(request); assertEquals(HttpResponseStatus.OK, responses.get(0).getStatus().getCode()); assertEquals("vadas", responses.get(0).getResult().getData().get(0)); @@ -1150,7 +1150,7 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration 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<ResponseMessage> 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 c5a8d53bac..8b46a6ab44 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 @@ -171,7 +171,7 @@ public class GremlinServerSslIntegrateTest extends AbstractGremlinServerIntegrat 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 62045069bc..52f8cdd4cc 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 class HttpRequestMessageDecoderTest { 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 class HttpRequestMessageDecoderTest { 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 class HttpRequestMessageDecoderTest { 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 class HttpRequestMessageDecoderTest { 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 2668b8c66d..8654e3dad0 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 final class Tokens { 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 a08c4abada..5b974926f2 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 final class RequestMessage { } /** - * 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<String, Object> otherBindings) { - Objects.requireNonNull(otherBindings, "bindings argument cannot be null."); - this.fields.put(Tokens.ARGS_BINDINGS, GremlinLang.convertParametersToString(otherBindings)); + public Builder addParameters(final Map<String, Object> 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 63c3893fb0..1013188eee 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 @@ -322,8 +322,8 @@ public abstract class AbstractGraphSONMessageSerializerV4 extends AbstractMessag 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 34243c29e0..69a32cc88f 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 @@ public final class 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 2f30d43b1d..6b523dd5f8 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 class RequestMessageSerializer { 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 0183712614..f4363c208d 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 @@ public abstract class AbstractCompatibilityTest { 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.<Map>getField(SerTokens.TOKEN_BINDINGS), recycled.getField(SerTokens.TOKEN_BINDINGS)); + assertEquals(resource.<Map>getField(SerTokens.TOKEN_PARAMETERS), recycled.getField(SerTokens.TOKEN_PARAMETERS)); assertEquals(resource.<String>getField(SerTokens.TOKEN_LANGUAGE), recycled.getField(SerTokens.TOKEN_LANGUAGE)); assertEquals(resource.<String>getField(SerTokens.TOKEN_G), recycled.getField(SerTokens.TOKEN_G)); assertEquals(resource.<Long>getField(SerTokens.TOKEN_TIMEOUT_MS), recycled.getField(SerTokens.TOKEN_TIMEOUT_MS)); assertEquals(resource.<String>getField(SerTokens.TOKEN_MATERIALIZE_PROPERTIES), recycled.getField(SerTokens.TOKEN_MATERIALIZE_PROPERTIES)); assertEquals(resource.getGremlin(), fromStatic.getGremlin()); - assertEquals(resource.<Map>getField(SerTokens.TOKEN_BINDINGS), fromStatic.getField(SerTokens.TOKEN_BINDINGS)); + assertEquals(resource.<Map>getField(SerTokens.TOKEN_PARAMETERS), fromStatic.getField(SerTokens.TOKEN_PARAMETERS)); assertEquals(resource.<String>getField(SerTokens.TOKEN_LANGUAGE), fromStatic.getField(SerTokens.TOKEN_LANGUAGE)); assertEquals(resource.<String>getField(SerTokens.TOKEN_G), fromStatic.getField(SerTokens.TOKEN_G)); assertEquals(resource.<Long>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 13376778a8..77a67b14b3 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 class RequestMessageTest { } @Test - public void shouldSetBindingsWithMap() { - final Map<String, Object> 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<String, Object> 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<String, Object> bindings = new HashMap<>(); - bindings.put("x", new Thread()); - RequestMessage.build("g.V()").addBindings(bindings); + public void shouldRejectUnsupportedTypeInParametersMap() { + final Map<String, Object> parameters = new HashMap<>(); + parameters.put("x", new Thread()); + RequestMessage.build("g.V()").addParameters(parameters); } @Test @@ -126,18 +126,18 @@ public class RequestMessageTest { final String g = "gmodern"; final String lang = "lang"; final String query = "g.V()"; - final Map<String, Object> bindings = new HashMap<>(); - bindings.put("b", "c"); - bindings.put("g", "gmodern"); + final Map<String, Object> 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<String, Object> 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 e8874bf502..e38ed20f01 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 class MessageSerializerTest { .addTimeoutMillis(500) .addG("g1") .addLanguage("some-lang") - .addBindings("['k':'v']") + .addParameters("['k':'v']") .create(); final ByteBuf buffer = serializer.serializeRequestAsBinary(request, allocator);
