You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2021/11/05 14:02:35 UTC
[tinkerpop] 01/01: TINKERPOP-2524 Supported more explicit numeric
literals in grammar
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a commit to branch TINKERPOP-2524
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit c2b4f2fc0a02e0022602978faf21bea205e56460
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Fri Nov 5 09:57:00 2021 -0400
TINKERPOP-2524 Supported more explicit numeric literals in grammar
Added byte, short, BigInteger, BigDecimal which basically just follows the pattern Java/Groovy have with a character suffix. While these literals have some specific use for Gremlin users they also have importance to the gherkin test suite where validating numeric semantics required a wider range of numeric types in the test definitions.
---
CHANGELOG.asciidoc | 1 +
docs/src/dev/developer/for-committers.asciidoc | 9 +-
.../language/grammar/GenericLiteralVisitor.java | 40 ++++--
.../grammar/GeneralLiteralVisitorTest.java | 133 +++++++++---------
.../Gherkin/CommonSteps.cs | 8 +-
.../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs | 7 +
.../test/cucumber/feature-steps.js | 2 +-
.../gremlin-javascript/test/cucumber/gremlin.js | 7 +
gremlin-language/src/main/antlr4/Gremlin.g4 | 4 +-
.../src/main/python/radish/feature_steps.py | 2 +-
gremlin-python/src/main/python/radish/gremlin.py | 7 +
.../server/handler/SaslAuthenticationHandler.java | 3 +-
gremlin-test/features/semantics/Equality.feature | 156 ++++++++++++++++++++-
.../tinkerpop/gremlin/features/StepDefinition.java | 11 +-
14 files changed, 291 insertions(+), 99 deletions(-)
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index af06a51..f2c6522 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -31,6 +31,7 @@ limitations under the License.
* Removed `groovy` and `groovy-json` dependencies from `gremlin-driver` as well as related `JsonBuilder` serialization support.
* Replaced log4j usage with logback where builds rely on and packaged distributions now contain the latter.
* Prevented metrics computation unless the traversal is in a locked state.
+* Added syntax to Gremlin grammar to explicitly define `byte`, `short` and `BigInteger`.
* Created a way to produce a corpus of Gremlin traversals via `FeatureReader` and `DocumentationReader` in `gremlin-language`.
* Exposed Gherkin tests as part of the provider test suite.
* Packaged Gherkin tests and data as standalone package as a convenience distribution.
diff --git a/docs/src/dev/developer/for-committers.asciidoc b/docs/src/dev/developer/for-committers.asciidoc
index 33465ee..c3c3453 100644
--- a/docs/src/dev/developer/for-committers.asciidoc
+++ b/docs/src/dev/developer/for-committers.asciidoc
@@ -357,11 +357,14 @@ they are required for the test.
the type notation system so that it is possible to have maps containing arbitrary keys and values.
* Numeric - *d[_xxx_]._y_* - The "xxx" should be replaced with a number. The suffix denoted by "y" should always be
included to further qualify the type of numeric. The following options are available:
-** *d* - 32-bit Double
-** *f* - 32-bit Float
+** *b* - 8-bit byte
+** *s* - 16-bit Short
** *i* - 32-bit Integer
+** *f* - 32-bit Float
** *l* - 64-bit Long
-** *m* - Arbitrary-precision signed decimal numbers (i.e. BigDecimal in Java)
+** *d* - 64-bit Double
+** *m* - Arbitrary-precision signed decimal numbers (e.g. `BigDecimal` in Java)
+** *n* - Arbitrary-precision integers (e.g. `BigInteger` in Java)
* Path - *p[_xxx_,_yyy_,_zzz_,...]* - A comma separated collection of values that make up the `Path` should be added to
between the square brackets. These values respect the type system thus allowing for creation of `Path` of vertices,
edges, maps, and any other available type.
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
index 1529392..1d93387 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
@@ -308,12 +308,25 @@ public class GenericLiteralVisitor extends GremlinBaseVisitor<Object> {
@Override
public Object visitIntegerLiteral(final GremlinParser.IntegerLiteralContext ctx) {
String integerLiteral = ctx.getText().toLowerCase().replace("_", "");
- // handle suffix: L/l
+ // handle suffixes for specific types
final int lastCharIndex = integerLiteral.length() - 1;
- if (integerLiteral.charAt(lastCharIndex) == 'l') {
- integerLiteral = integerLiteral.substring(0, lastCharIndex);
-
- return Long.decode(integerLiteral);
+ final char suffix = integerLiteral.charAt(lastCharIndex);
+ switch (suffix) {
+ case 'b':
+ integerLiteral = integerLiteral.substring(0, lastCharIndex);
+ return Byte.decode(integerLiteral);
+ case 's':
+ integerLiteral = integerLiteral.substring(0, lastCharIndex);
+ return Short.decode(integerLiteral);
+ case 'i':
+ integerLiteral = integerLiteral.substring(0, lastCharIndex);
+ return Integer.decode(integerLiteral);
+ case 'l':
+ integerLiteral = integerLiteral.substring(0, lastCharIndex);
+ return Long.decode(integerLiteral);
+ case 'n':
+ integerLiteral = integerLiteral.substring(0, lastCharIndex);
+ return new BigInteger(integerLiteral);
}
try {
@@ -363,18 +376,19 @@ public class GenericLiteralVisitor extends GremlinBaseVisitor<Object> {
final String floatLiteral = ctx.getText().toLowerCase();
// check suffix
- final char lastCharacter = floatLiteral.charAt(floatLiteral.length() - 1);
- if (Character.isDigit(lastCharacter)) {
- // if there is no suffix, parse it as BigDecimal
- return new BigDecimal(floatLiteral);
- }
-
- if (lastCharacter == 'f') {
+ final int lastCharIndex = floatLiteral.length() - 1;
+ final char lastCharacter = floatLiteral.charAt(lastCharIndex);
+ if (lastCharacter == 'm') {
+ // parse M/m or whatever which could be a parse exception
+ return new BigDecimal(floatLiteral.substring(0, lastCharIndex));
+ } else if (lastCharacter == 'f') {
// parse F/f suffix as Float
return new Float(ctx.getText());
- } else {
+ } else if (lastCharacter == 'd'){
// parse D/d suffix as Double
return new Double(floatLiteral);
+ } else {
+ return new BigDecimal(floatLiteral);
}
}
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
index c8a350e..7791a08 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
@@ -292,44 +292,54 @@ public class GeneralLiteralVisitorTest {
public String script;
@Parameterized.Parameter(value = 1)
- public String expected;
+ public Object expected;
@Parameterized.Parameters(name = "{0}")
public static Iterable<Object[]> generateTestParameters() {
return Arrays.asList(new Object[][]{
// decimal format
- {"1", "1"},
- {"-11", "-11"},
- {"0", "0"},
- {"1L", "1L"},
- {"-1l", "-1l"},
- {"1_2_3", "123"},
- {"-1_2_3L", "-123L"},
- {"9223372036854775807", "9223372036854775807"},
- {"-9223372036854775808", "-9223372036854775808"},
- {"9223372036854775807L", "9223372036854775807"},
- {"-9223372036854775808l", "-9223372036854775808"},
+ {"1", 1},
+ {"-11", -11},
+ {"0", 0},
+ {"1B", (byte) 1},
+ {"-1b", (byte) -1},
+ {"1S", (short) 1},
+ {"-1s", (short) -1},
+ {"1I", 1},
+ {"-1i", -1},
+ {"1L", 1L},
+ {"-1l", -1L},
+ {"1_2_3", 123},
+ {"-1_2_3L", -123L},
+ {"1N", new BigInteger("1")},
+ {"-1n", new BigInteger("-1")},
+ {"9223372036854775807", 9223372036854775807L},
+ {"-9223372036854775808", -9223372036854775808L},
+ {"9223372036854775807L", 9223372036854775807L},
+ {"-9223372036854775808l", -9223372036854775808L},
+ {"9999999999999999999999999999999999999999999999999N", new BigInteger("9999999999999999999999999999999999999999999999999")},
+ {"9999999999999999999999999999999999999999999999999n", new BigInteger("9999999999999999999999999999999999999999999999999")},
// hex format
- {"0xA", "10"},
- {"-0xA", "-10"},
- {"0xaL", "10l"},
- {"-0xal", "-10l"},
- {"-0xA_0L", "-160l"},
- {"0x10", "16"},
- {"-0x10", "-16"},
- {"0x10", "16"},
- {"-0x10l", "-16l"},
- {"-0x1_0L", "-16l"},
+ {"0xA", 10},
+ {"-0xA", -10},
+ {"0xaL", 10L},
+ {"-0xal", -10L},
+ {"-0xA_0L", -160L},
+ {"0x10", 16},
+ {"-0x10", -16},
+ {"0x10", 16},
+ {"-0x10l", -16L},
+ {"-0x1_0L", -16L},
// oct format
- {"01", "1"},
- {"-01", "-1"},
- {"01L", "1l"},
- {"-01l", "-1l"},
- {"010", "8"},
- {"-010", "-8"},
- {"010L", "8l"},
- {"-010l", "-8l"},
- {"-01_0L", "-8l"},
+ {"01", 1},
+ {"-01", -1},
+ {"01L", 1L},
+ {"-01l", -1L},
+ {"010", 8},
+ {"-010", -8},
+ {"010L", 8L},
+ {"-010l", -8L},
+ {"-01_0L", -8L},
});
}
@@ -340,19 +350,7 @@ public class GeneralLiteralVisitorTest {
final GremlinParser.IntegerLiteralContext ctx = parser.integerLiteral();
final Object actualValue = GenericLiteralVisitor.getInstance().visitIntegerLiteral(ctx);
-
- // verify suffix L/l
- if (expected.toUpperCase().charAt(expected.length() - 1) == 'L') {
- assertEquals(Long.valueOf(expected.substring(0, expected.length() - 1)), actualValue);
- return;
- }
-
- // based on value range verify the value is parsed in correct type
- try {
- assertEquals(Integer.valueOf(expected), actualValue);
- } catch (NumberFormatException ignoredException) {
- assertEquals(Long.valueOf(expected), actualValue);
- }
+ assertEquals(expected, actualValue);
}
}
@@ -398,34 +396,33 @@ public class GeneralLiteralVisitorTest {
public String script;
@Parameterized.Parameter(value = 1)
- public String expected;
-
- @Parameterized.Parameter(value = 2)
- public String type;
+ public Object expected;
@Parameterized.Parameters()
public static Iterable<Object[]> generateTestParameters() {
return Arrays.asList(new Object[][]{
- {"1.1", "1.1", "java.math.BigDecimal"},
- {"-0.1", "-0.1", "java.math.BigDecimal"},
- {"1.0E+12", "1.0E12", "java.math.BigDecimal"},
- {"-0.1E-12", "-0.1E-12", "java.math.BigDecimal"},
- {"1E12", "1E12", "java.math.BigDecimal"},
+ {"1.1m", new BigDecimal("1.1")},
+ {"1.1M", new BigDecimal("1.1")},
+ {"1.1", new BigDecimal("1.1")},
+ {"-0.1", new BigDecimal("-0.1")},
+ {"1.0E+12", new BigDecimal("1.0E12")},
+ {"-0.1E-12", new BigDecimal("-0.1E-12")},
+ {"1E12", new BigDecimal("1E12")},
// float
- {"1.1f", "1.1", "java.lang.Float"},
- {"-0.1F", "-0.1", "java.lang.Float"},
- {"1.0E+12f", "1.0E12", "java.lang.Float"},
- {"-0.1E-12F", "-0.1E-12", "java.lang.Float"},
- {"1E12f", "1E12", "java.lang.Float"},
- {"1F", "1", "java.lang.Float"},
+ {"1.1f", 1.1F},
+ {"-0.1F", -0.1F},
+ {"1.0E+12f", 1.0E12F},
+ {"-0.1E-12F", -0.1E-12F},
+ {"1E12f", 1E12F},
+ {"1F", 1F},
// double
- {"1.1d", "1.1", "java.lang.Double"},
- {"-0.1D", "-0.1", "java.lang.Double"},
- {"1.0E+12d", "1.0E12", "java.lang.Double"},
- {"-0.1E-12D", "-0.1E-12", "java.lang.Double"},
- {"1E12d", "1E12", "java.lang.Double"},
- {"1D", "1", "java.lang.Double"}
+ {"1.1d", 1.1D},
+ {"-0.1D", -0.1D},
+ {"1.0E+12d", 1.0E12D},
+ {"-0.1E-12D", -0.1E-12D},
+ {"1E12d", 1E12D},
+ {"1D", 1D}
});
}
@@ -435,11 +432,7 @@ public class GeneralLiteralVisitorTest {
final GremlinParser parser = new GremlinParser(new CommonTokenStream(lexer));
final GremlinParser.FloatLiteralContext ctx = parser.floatLiteral();
- final Class<?> clazz = Class.forName(type);
- final Constructor<?> ctor = clazz.getConstructor(String.class);
- final Object expectedValue = ctor.newInstance(expected);
-
- assertEquals(expectedValue, GenericLiteralVisitor.getInstance().visitFloatLiteral(ctx));
+ assertEquals(expected, GenericLiteralVisitor.getInstance().visitFloatLiteral(ctx));
}
}
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
index a2941eb..11e71c8 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
@@ -26,6 +26,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
+using System.Numerics;
using System.Text.Json;
using System.Text.RegularExpressions;
using Gherkin.Ast;
@@ -54,7 +55,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
private static readonly IDictionary<Regex, Func<string, string, object>> Parsers =
new Dictionary<string, Func<string, string, object>>
{
- {@"d\[(.*)\]\.([ilfdm])", ToNumber},
+ {@"d\[(.*)\]\.([bsilfdmn])", ToNumber},
{@"D\[(.+)\]", ToDirection},
{@"v\[(.+)\]", ToVertex},
{@"v\[(.+)\]\.id", (x, graphName) => ToVertex(x, graphName).Id},
@@ -74,11 +75,14 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
private static readonly IDictionary<char, Func<string, object>> NumericParsers =
new Dictionary<char, Func<string, object>>
{
+ { 'b', s => Convert.ToByte(s) },
+ { 's', s => Convert.ToInt16(s) },
{ 'i', s => Convert.ToInt32(s) },
{ 'l', s => Convert.ToInt64(s) },
{ 'f', s => Convert.ToSingle(s, CultureInfo.InvariantCulture) },
{ 'd', s => Convert.ToDouble(s, CultureInfo.InvariantCulture) },
- { 'm', s => Convert.ToDecimal(s, CultureInfo.InvariantCulture) }
+ { 'm', s => Convert.ToDecimal(s, CultureInfo.InvariantCulture) },
+ { 'n', s => BigInteger.Parse(s) }
};
[Given("the (\\w+) graph")]
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index 2c8d242..bb8565b 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -686,7 +686,14 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_hasLabelXpersonX_V_hasLabelXsoftwareX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").V().HasLabel("software").Values<object>("name")}},
{"g_V_hasLabelXloopsX_bothEXselfX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("loops").BothE("self")}},
{"g_V_hasLabelXloopsX_bothXselfX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("loops").Both("self")}},
+ {"Primitives_Number_eqXbyteX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Unfold<object>().Where(__.Is(p["xx2"]))}},
+ {"Primitives_Number_eqXshortX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Unfold<object>().Where(__.Is(p["xx2"]))}},
{"Primitives_Number_eqXintX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Unfold<object>().Where(__.Is(p["xx2"]))}},
+ {"Primitives_Number_eqXlongX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Unfold<object>().Where(__.Is(p["xx2"]))}},
+ {"Primitives_Number_eqXbigintX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Unfold<object>().Where(__.Is(p["xx2"]))}},
+ {"Primitives_Number_eqXfloatX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Unfold<object>().Where(__.Is(p["xx2"]))}},
+ {"Primitives_Number_eqXdoubleX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Unfold<object>().Where(__.Is(p["xx2"]))}},
+ {"Primitives_Number_eqXbigdecimalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Unfold<object>().Where(__.Is(p["xx2"]))}},
{"g_V_valueXnameX_aggregateXxX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Aggregate("x").Cap<object>("x")}},
{"g_V_valueXnameX_aggregateXglobal_xX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Aggregate(Scope.Global,"x").Cap<object>("x")}},
{"g_V_aggregateXxX_byXnameX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("x").By("name").Cap<object>("x")}},
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
index 7a9c8ee..e9d39cf 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
@@ -42,7 +42,7 @@ const direction = traversalModule.direction;
const mapAsObject = false;
const parsers = [
- [ 'd\\[(.*)\\]\\.[ilfdm]', toNumeric ],
+ [ 'd\\[(.*)\\]\\.[bsilfdmn]', toNumeric ],
[ 'v\\[(.+)\\]', toVertex ],
[ 'v\\[(.+)\\]\\.id', toVertexId ],
[ 'v\\[(.+)\\]\\.sid', toVertexIdString ],
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
index 8507405..a780192 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
@@ -675,7 +675,14 @@ const gremlins = {
g_V_hasLabelXpersonX_V_hasLabelXsoftwareX_name: [function({g}) { return g.V().hasLabel("person").V().hasLabel("software").values("name") }],
g_V_hasLabelXloopsX_bothEXselfX: [function({g}) { return g.V().hasLabel("loops").bothE("self") }],
g_V_hasLabelXloopsX_bothXselfX: [function({g}) { return g.V().hasLabel("loops").both("self") }],
+ Primitives_Number_eqXbyteX: [function({g, xx1, xx2}) { return g.inject(xx1).unfold().where(__.is(xx2)) }],
+ Primitives_Number_eqXshortX: [function({g, xx1, xx2}) { return g.inject(xx1).unfold().where(__.is(xx2)) }],
Primitives_Number_eqXintX: [function({g, xx1, xx2}) { return g.inject(xx1).unfold().where(__.is(xx2)) }],
+ Primitives_Number_eqXlongX: [function({g, xx1, xx2}) { return g.inject(xx1).unfold().where(__.is(xx2)) }],
+ Primitives_Number_eqXbigintX: [function({g, xx1, xx2}) { return g.inject(xx1).unfold().where(__.is(xx2)) }],
+ Primitives_Number_eqXfloatX: [function({g, xx1, xx2}) { return g.inject(xx1).unfold().where(__.is(xx2)) }],
+ Primitives_Number_eqXdoubleX: [function({g, xx1, xx2}) { return g.inject(xx1).unfold().where(__.is(xx2)) }],
+ Primitives_Number_eqXbigdecimalX: [function({g, xx1, xx2}) { return g.inject(xx1).unfold().where(__.is(xx2)) }],
g_V_valueXnameX_aggregateXxX_capXxX: [function({g}) { return g.V().values("name").aggregate("x").cap("x") }],
g_V_valueXnameX_aggregateXglobal_xX_capXxX: [function({g}) { return g.V().values("name").aggregate(Scope.global,"x").cap("x") }],
g_V_aggregateXxX_byXnameX_capXxX: [function({g}) { return g.V().aggregate("x").by("name").cap("x") }],
diff --git a/gremlin-language/src/main/antlr4/Gremlin.g4 b/gremlin-language/src/main/antlr4/Gremlin.g4
index 0844d67..e277baa 100644
--- a/gremlin-language/src/main/antlr4/Gremlin.g4
+++ b/gremlin-language/src/main/antlr4/Gremlin.g4
@@ -1362,7 +1362,7 @@ OctalIntegerLiteral
fragment
IntegerTypeSuffix
- : [lL]
+ : [bBsSnNiIlL]
;
fragment
@@ -1489,7 +1489,7 @@ Sign
fragment
FloatTypeSuffix
- : [fFdD]
+ : [fFdDmM]
;
// Boolean Literals
diff --git a/gremlin-python/src/main/python/radish/feature_steps.py b/gremlin-python/src/main/python/radish/feature_steps.py
index eb225bd..9fd8cf6 100644
--- a/gremlin-python/src/main/python/radish/feature_steps.py
+++ b/gremlin-python/src/main/python/radish/feature_steps.py
@@ -162,7 +162,7 @@ def _convert(val, ctx):
return [] if val == "l[]" else list(map((lambda x: _convert(x, ctx)), val[2:-1].split(",")))
elif isinstance(val, str) and re.match(r"^s\[.*\]$", val): # parse set
return set() if val == "s[]" else set(map((lambda x: _convert(x, ctx)), val[2:-1].split(",")))
- elif isinstance(val, str) and re.match(r"^d\[.*\]\.[ilfdm]$", val): # parse numeric
+ elif isinstance(val, str) and re.match(r"^d\[.*\]\.[bsilfdmn]$", val): # parse numeric
return float(val[2:-3]) if val[2:-3].__contains__(".") else long(val[2:-3])
elif isinstance(val, str) and re.match(r"^v\[.*\]\.id$", val): # parse vertex id
return __find_cached_element(ctx, graph_name, val[2:-4], "v").id
diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py
index 5f9535a..0aa4c93 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -660,7 +660,14 @@ world.gremlins = {
'g_V_hasLabelXpersonX_V_hasLabelXsoftwareX_name': [(lambda g:g.V().hasLabel('person').V().hasLabel('software').name)],
'g_V_hasLabelXloopsX_bothEXselfX': [(lambda g:g.V().hasLabel('loops').bothE('self'))],
'g_V_hasLabelXloopsX_bothXselfX': [(lambda g:g.V().hasLabel('loops').both('self'))],
+ 'Primitives_Number_eqXbyteX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).unfold().where(__.is_(xx2)))],
+ 'Primitives_Number_eqXshortX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).unfold().where(__.is_(xx2)))],
'Primitives_Number_eqXintX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).unfold().where(__.is_(xx2)))],
+ 'Primitives_Number_eqXlongX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).unfold().where(__.is_(xx2)))],
+ 'Primitives_Number_eqXbigintX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).unfold().where(__.is_(xx2)))],
+ 'Primitives_Number_eqXfloatX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).unfold().where(__.is_(xx2)))],
+ 'Primitives_Number_eqXdoubleX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).unfold().where(__.is_(xx2)))],
+ 'Primitives_Number_eqXbigdecimalX': [(lambda g, xx1=None,xx2=None:g.inject(xx1).unfold().where(__.is_(xx2)))],
'g_V_valueXnameX_aggregateXxX_capXxX': [(lambda g:g.V().name.aggregate('x').cap('x'))],
'g_V_valueXnameX_aggregateXglobal_xX_capXxX': [(lambda g:g.V().name.aggregate(Scope.global_,'x').cap('x'))],
'g_V_aggregateXxX_byXnameX_capXxX': [(lambda g:g.V().aggregate('x').by('name').cap('x'))],
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SaslAuthenticationHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SaslAuthenticationHandler.java
index 2adc97f..848be27 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SaslAuthenticationHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/SaslAuthenticationHandler.java
@@ -156,8 +156,7 @@ public class SaslAuthenticationHandler extends AbstractAuthenticationHandler {
ctx.writeAndFlush(error);
}
}
- }
- else {
+ } else {
logger.warn("{} only processes RequestMessage instances - received {} - channel closing",
this.getClass().getSimpleName(), msg.getClass());
ctx.close();
diff --git a/gremlin-test/features/semantics/Equality.feature b/gremlin-test/features/semantics/Equality.feature
index cb57121..58a1439 100644
--- a/gremlin-test/features/semantics/Equality.feature
+++ b/gremlin-test/features/semantics/Equality.feature
@@ -18,11 +18,52 @@
@StepClassSemantics
Feature: Equality
- # TODO: TINKERPOP-2524 to support all the number types (and others required for semantics checks)
+ @GraphComputerVerificationInjectionNotSupported
+ Scenario: Primitives_Number_eqXbyteX
+ Given the empty graph
+ And using the parameter xx1 defined as "l[d[1].b,d[1].s,d[1].i,d[1].l,d[1].f,d[1].d,d[1000].i,d[1].m,d[1].n]"
+ And using the parameter xx2 defined as "d[1].b"
+ And the traversal of
+ """
+ g.inject(xx1).unfold().where(__.is(xx2))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[1].i |
+ | d[1].l |
+ | d[1].f |
+ | d[1].d |
+ | d[1].s |
+ | d[1].n |
+ | d[1].m |
+ | d[1].b |
+
+ @GraphComputerVerificationInjectionNotSupported
+ Scenario: Primitives_Number_eqXshortX
+ Given the empty graph
+ And using the parameter xx1 defined as "l[d[1].b,d[1].s,d[1].i,d[1].l,d[1].f,d[1].d,d[1000].i,d[1].m,d[1].n]"
+ And using the parameter xx2 defined as "d[1].s"
+ And the traversal of
+ """
+ g.inject(xx1).unfold().where(__.is(xx2))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[1].i |
+ | d[1].l |
+ | d[1].f |
+ | d[1].d |
+ | d[1].s |
+ | d[1].n |
+ | d[1].m |
+ | d[1].b |
+
@GraphComputerVerificationInjectionNotSupported
Scenario: Primitives_Number_eqXintX
Given the empty graph
- And using the parameter xx1 defined as "l[d[1].i,d[1].l,d[1].f,d[1].d,d[1000].i]"
+ And using the parameter xx1 defined as "l[d[1].b,d[1].s,d[1].i,d[1].l,d[1].f,d[1].d,d[1000].i,d[1].m,d[1].n]"
And using the parameter xx2 defined as "d[1].i"
And the traversal of
"""
@@ -34,4 +75,113 @@ Feature: Equality
| d[1].i |
| d[1].l |
| d[1].f |
- | d[1].d |
\ No newline at end of file
+ | d[1].d |
+ | d[1].s |
+ | d[1].n |
+ | d[1].m |
+ | d[1].b |
+
+ @GraphComputerVerificationInjectionNotSupported
+ Scenario: Primitives_Number_eqXlongX
+ Given the empty graph
+ And using the parameter xx1 defined as "l[d[1].b,d[1].s,d[1].i,d[1].l,d[1].f,d[1].d,d[1000].i,d[1].m,d[1].n]"
+ And using the parameter xx2 defined as "d[1].l"
+ And the traversal of
+ """
+ g.inject(xx1).unfold().where(__.is(xx2))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[1].i |
+ | d[1].l |
+ | d[1].f |
+ | d[1].d |
+ | d[1].s |
+ | d[1].n |
+ | d[1].m |
+ | d[1].b |
+
+ @GraphComputerVerificationInjectionNotSupported
+ Scenario: Primitives_Number_eqXbigintX
+ Given the empty graph
+ And using the parameter xx1 defined as "l[d[1].b,d[1].s,d[1].i,d[1].l,d[1].f,d[1].d,d[1000].i,d[1].m,d[1].n]"
+ And using the parameter xx2 defined as "d[1].n"
+ And the traversal of
+ """
+ g.inject(xx1).unfold().where(__.is(xx2))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[1].i |
+ | d[1].l |
+ | d[1].f |
+ | d[1].d |
+ | d[1].s |
+ | d[1].n |
+ | d[1].m |
+ | d[1].b |
+
+ @GraphComputerVerificationInjectionNotSupported
+ Scenario: Primitives_Number_eqXfloatX
+ Given the empty graph
+ And using the parameter xx1 defined as "l[d[1].b,d[1].s,d[1].i,d[1].l,d[1].f,d[1].d,d[1000].i,d[1].m,d[1].n]"
+ And using the parameter xx2 defined as "d[1].f"
+ And the traversal of
+ """
+ g.inject(xx1).unfold().where(__.is(xx2))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[1].i |
+ | d[1].l |
+ | d[1].f |
+ | d[1].d |
+ | d[1].s |
+ | d[1].n |
+ | d[1].m |
+ | d[1].b |
+
+ @GraphComputerVerificationInjectionNotSupported
+ Scenario: Primitives_Number_eqXdoubleX
+ Given the empty graph
+ And using the parameter xx1 defined as "l[d[1].b,d[1].s,d[1].i,d[1].l,d[1].f,d[1].d,d[1000].i,d[1].m,d[1].n]"
+ And using the parameter xx2 defined as "d[1].d"
+ And the traversal of
+ """
+ g.inject(xx1).unfold().where(__.is(xx2))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[1].i |
+ | d[1].l |
+ | d[1].f |
+ | d[1].d |
+ | d[1].s |
+ | d[1].n |
+ | d[1].m |
+ | d[1].b |
+
+ @GraphComputerVerificationInjectionNotSupported
+ Scenario: Primitives_Number_eqXbigdecimalX
+ Given the empty graph
+ And using the parameter xx1 defined as "l[d[1].b,d[1].s,d[1].i,d[1].l,d[1].f,d[1].d,d[1000].i,d[1].m,d[1].n]"
+ And using the parameter xx2 defined as "d[1].m"
+ And the traversal of
+ """
+ g.inject(xx1).unfold().where(__.is(xx2))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[1].i |
+ | d[1].l |
+ | d[1].f |
+ | d[1].d |
+ | d[1].s |
+ | d[1].n |
+ | d[1].m |
+ | d[1].b |
\ No newline at end of file
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
index 410858c..6b644a0 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
@@ -56,6 +56,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.math.BigDecimal;
+import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -93,11 +94,14 @@ public final class StepDefinition {
final String listItems = Stream.of(items).map(String::trim).map(x -> convertToString(x)).collect(Collectors.joining(","));
return String.format("[%s]", listItems);
}));
- add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.i"), s -> s));
+ add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.b"), s -> s + "b"));
+ add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.s"), s -> s + "s"));
+ add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.i"), s -> s + "i"));
add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.l"), s -> s + "l"));
add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.f"), s -> s + "f"));
add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.d"), s -> s + "d"));
- add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.m"), s -> String.format("new BigDecimal(%s)", s)));
+ add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.m"), s -> s + "m"));
+ add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.n"), s -> s + "n"));
add(Pair.with(Pattern.compile("v\\[(.+)\\]\\.id"), s -> g.V().has("name", s).id().next().toString()));
add(Pair.with(Pattern.compile("v\\[(.+)\\]\\.sid"), s -> g.V().has("name", s).id().next().toString()));
@@ -155,11 +159,14 @@ public final class StepDefinition {
throw new AssumptionViolatedException("This test uses a Path as a parameter which is not supported by gremlin-language");
}));
+ add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.b"), Byte::parseByte));
+ add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.s"), Short::parseShort));
add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.i"), Integer::parseInt));
add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.l"), Long::parseLong));
add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.f"), Float::parseFloat));
add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.d"), Double::parseDouble));
add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.m"), BigDecimal::new));
+ add(Pair.with(Pattern.compile("d\\[(.*)\\]\\.n"), BigInteger::new));
add(Pair.with(Pattern.compile("v\\[(.+)\\]\\.id"), s -> g.V().has("name", s).id().next()));
add(Pair.with(Pattern.compile("v\\[(.+)\\]\\.sid"), s -> g.V().has("name", s).id().next().toString()));