Skip to content

Commit 49cad09

Browse files
committed
Merge branch '3.8-dev'
2 parents 30dca96 + 619e1f7 commit 49cad09

41 files changed

Lines changed: 2203 additions & 953 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.asciidoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,11 @@ This release also includes changes from <<release-3-7-XXX, 3.7.XXX>>.
104104
* Removed the deprecated `withGraph()` option from `AnonymousTraversalSource`.
105105
* Modified the `split()` step to split a string into a list of its characters if the given separator is an empty string.
106106
* Changed `GremlinLangScriptEngine` via `GenericLiteralVisitor` to treat floating-point literals as `Double` by default instead of `BigDecimal` for better alignment with common programming language conventions.
107+
* Modified the Gremlin grammar to to treat `Infinity` and `NaN` as floating-points.
107108
* Added `withoutStrategies()` syntax to the Gremlin ANTLR grammar.
108109
* Modified the Gremlin ANTLR grammar to more dynamically interact with any strategies registered globally to the `TraversalStrategies` cache sets.
109110
* Made `new` keyword optional in the Gremlin grammar.
111+
* Allowed keywords to be used as `Map` keys when defined using the shorthand without quotes.
110112
* Added integer overflow checks.
111113
* Added missing strategies to the `TraversalStrategies` global cache as well as `CoreImports` in `gremlin-groovy`.
112114
* Added missing strategies to `strategies.py` in `gremlin-python`.

docs/src/upgrade/release-3.8.x.asciidoc

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ these were deserialized into arrays.
7979
8080
==== Gremlin Grammar Changes
8181
82-
A number of changes have been introduce to the Gremlin grammar to help make it be more consistent and easier to use.
82+
A number of changes have been introduced to the Gremlin grammar to help make it be more consistent and easier to use.
8383
8484
*`new` keyword is now optional*
8585
@@ -98,16 +98,79 @@ In a future version, it is likely that the `new` keyword will be removed entirel
9898
*Supports withoutStrategies()*
9999
100100
The `withoutStrategies()` configuration step is now supported syntax for the grammar. While this option is not commonly
101-
used it is still a part of the Gremlin language and there are times where it is helpful to have this fine grained
101+
used it is still a part of the Gremlin language and there are times where it is helpful to have this fine-grained
102102
control over how a traversal works.
103103
104104
[source,groovy]
105105
----
106106
g.V().withoutStrategies(CountStrategy)
107107
----
108108
109+
*`Map` keys restrictions*
110+
111+
Earlier versions of the grammar allowed a wide range of values for the keys. In many cases, these didn't really make
112+
sense for Gremlin and were just inherited from the Groovy language since Gremlin tends to follow that language in many
113+
ways. That said, Gremlin did take some liberties with that syntax and introduced its own shorthand for some cases. Those
114+
shorthands created unfortunate situations where certain words were being prevented as being able to be used as keys
115+
which could lead to confusion.
116+
117+
A `Map` is still defined in the same way it always has been, where the following two lines produce an equivalent `Map`:
118+
119+
[source,groovy]
120+
----
121+
[label: 100]
122+
["label": 100]
123+
----
124+
125+
Note that when quotes are not use to denote a string, Gremlin will assume that the intention is to shorthand a string
126+
key and not reference a Gremlin keyword. To reference an allowable keyword as the key, either wrap it with parenthesis
127+
or use its longhand form as shown in the following examples which all produce the same `Map`:
128+
129+
[source,groovy]
130+
----
131+
[T.id: 100]
132+
[(T.id): 100]
133+
[(id): 100]
134+
----
135+
136+
Note that the first example is a Gremlin convenience that is not compatible in Groovy. This does produce a syntax error
137+
in Groovy's case. When upgrading to 3.8.0, it will be important to evaluate any code that is using scripts with `Map`
138+
keys that match keywords that are not wrapped in parentheses. On upgrade they will begin to be treated as `String` keys
139+
rather than their `Enum` value. This is particularly relevant for `property(Map)`, `mergeV` and `mergeE` which use a
140+
'Map` for their arguments and commonly require that `T` and `Direction` be used as keys.
141+
142+
The following examples show some `Map` usage from older versions that will work without need for changes in 3.8.0:
143+
144+
[source,groovy]
145+
----
146+
// the long forms are used and each are wrapped in parenthesis
147+
g.mergeE([(T.label):'Sibling',created:'2022-02-07',(Direction.from):1,(Direction.to):2])
148+
149+
// the short forms are used and each are wrapped in parenthesis
150+
g.mergeE([(label):'Sibling',created:'2022-02-07',(Direction.from):1,(Direction.to):2])
151+
152+
// the long forms are used and for Gremlin this is a syntax convenience to spare typing
153+
// the parenthesis
154+
g.mergeE([T.label:'Sibling',created:'2022-02-07',Direction.from:1,Direction.to:2])
155+
156+
// while the following line mixes qualified enums with T and uses shorthand for Direction
157+
// with from and to all of the enums are wrapped in parenthesis
158+
g.mergeE([(T.label):'Sibling',created:'2022-02-07',(from):1,(to):2])
159+
----
160+
161+
In this next example, the `Map` keys are defined in a way that changes will be necessary in 3.8.0:
162+
163+
[source,groovy]
164+
----
165+
// none of the keys below are qualified with their enum long form nor are they wrapped in
166+
// parenthesis and as a result will be treated as String key values in 3.8.0 unless a
167+
// change is made
168+
g.mergeE([label:'Sibling',created:'2022-02-07',from:1,to:2])
169+
----
170+
109171
See: link:https://issues.apache.org/jira/browse/TINKERPOP-2862[TINKERPOP-2862],
110-
link:https://issues.apache.org/jira/browse/TINKERPOP-3046[TINKERPOP-3046]
172+
link:https://issues.apache.org/jira/browse/TINKERPOP-3046[TINKERPOP-3046],
173+
link:https://issues.apache.org/jira/browse/TINKERPOP-3047[TINKERPOP-3047]
111174
112175
==== SeedStrategy Construction
113176

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitor.java

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,13 @@
1818
*/
1919
package org.apache.tinkerpop.gremlin.language.grammar;
2020

21-
import org.apache.tinkerpop.gremlin.process.traversal.GremlinTypeErrorException;
2221
import org.apache.tinkerpop.gremlin.process.traversal.step.GType;
2322
import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
23+
import org.apache.tinkerpop.gremlin.structure.Vertex;
2424
import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
2525

2626
import java.lang.reflect.Array;
27+
import java.util.Date;
2728
import java.util.Map;
2829
import java.util.Objects;
2930

@@ -38,6 +39,62 @@ public ArgumentVisitor(final VariableResolver resolver, final GremlinAntlrToJava
3839
this.antlr = antlr;
3940
}
4041

42+
/**
43+
* Wrapper to visit function for boolean.
44+
*/
45+
public boolean parseBoolean(final GremlinParser.BooleanArgumentContext ctx) {
46+
return (boolean) visitBooleanArgument(ctx);
47+
}
48+
49+
/**
50+
* Wrapper to visit function for integer types.
51+
*/
52+
public Number parseNumber(final GremlinParser.IntegerArgumentContext ctx) {
53+
return (Number) visitIntegerArgument(ctx);
54+
}
55+
56+
/**
57+
* Wrapper to visit function for float types.
58+
*/
59+
public Number parseNumber(final GremlinParser.FloatArgumentContext ctx) {
60+
return (Number) visitFloatArgument(ctx);
61+
}
62+
63+
/**
64+
* Wrapper to visit function for string types.
65+
*/
66+
public String parseString(final GremlinParser.StringArgumentContext ctx) {
67+
return (String) visitStringArgument(ctx);
68+
}
69+
70+
/**
71+
* Wrapper to visit function for Date type.
72+
*/
73+
public Date parseDate(final GremlinParser.DateArgumentContext ctx) {
74+
return (Date) visitDateArgument(ctx);
75+
}
76+
77+
/**
78+
* Wrapper for visit function for object types.
79+
*/
80+
public Object parseObject(final GremlinParser.GenericLiteralArgumentContext ctx) {
81+
return visitGenericLiteralArgument(ctx);
82+
}
83+
84+
/**
85+
* Wrapper for visit function for {@link Vertex} types.
86+
*/
87+
public Vertex parseVertex(final GremlinParser.StructureVertexArgumentContext ctx) {
88+
return (Vertex) visitStructureVertexArgument(ctx);
89+
}
90+
91+
/**
92+
* Wrapper for visit function for {@code Map} types.
93+
*/
94+
public Map parseMap(final GremlinParser.GenericLiteralMapArgumentContext ctx) {
95+
return (Map) visitGenericLiteralMapArgument(ctx);
96+
}
97+
4198
/**
4299
* Wrapper for visit function for {@code Map} types.
43100
*/
@@ -76,13 +133,13 @@ public Object[] parseObjectVarargs(final GremlinParser.GenericLiteralListArgumen
76133
}
77134

78135
/**
79-
* Parse a string argument varargs, and return an string array
136+
* Parse a string literal varargs, and return a string array
80137
*/
81-
public GValue<String>[] parseStringVarargs(final GremlinParser.StringLiteralVarargsContext varargsContext) {
82-
if (varargsContext == null || varargsContext.stringNullableArgument() == null) {
138+
public GValue<String>[] parseStringVarargs(final GremlinParser.StringLiteralVarargsArgumentContext varargsArgumentContext) {
139+
if (varargsArgumentContext == null || varargsArgumentContext.stringNullableArgument() == null) {
83140
return new GValue[0];
84141
}
85-
return varargsContext.stringNullableArgument()
142+
return varargsArgumentContext.stringNullableArgument()
86143
.stream()
87144
.filter(Objects::nonNull)
88145
.map(antlr.argumentVisitor::parseString)

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,7 +1082,7 @@ protected void notImplemented(final ParseTree ctx) {
10821082
/**
10831083
* {@inheritDoc}
10841084
*/
1085-
@Override public T visitTraversalToken(final GremlinParser.TraversalTokenContext ctx) { notImplemented(ctx); return null; }
1085+
@Override public T visitTraversalT(final GremlinParser.TraversalTContext ctx) { notImplemented(ctx); return null; }
10861086
/**
10871087
* {@inheritDoc}
10881088
*/
@@ -1621,10 +1621,6 @@ protected void notImplemented(final ParseTree ctx) {
16211621
* {@inheritDoc}
16221622
*/
16231623
@Override public T visitGenericLiteralListArgument(GremlinParser.GenericLiteralListArgumentContext ctx) { notImplemented(ctx); return null; }
1624-
/**
1625-
* {@inheritDoc}
1626-
*/
1627-
@Override public T visitStructureVertexArgument(GremlinParser.StructureVertexArgumentContext ctx) { notImplemented(ctx); return null; }
16281624
/**
16291625
* {@inheritDoc}
16301626
*/
@@ -1681,4 +1677,40 @@ protected void notImplemented(final ParseTree ctx) {
16811677
* {@inheritDoc}
16821678
*/
16831679
@Override public T visitGenericLiteralSet(final GremlinParser.GenericLiteralSetContext ctx) { notImplemented(ctx); return null; }
1680+
/**
1681+
* {@inheritDoc}
1682+
*/
1683+
@Override public T visitTraversalTShort(final GremlinParser.TraversalTShortContext ctx) { notImplemented(ctx); return null; }
1684+
/**
1685+
* {@inheritDoc}
1686+
*/
1687+
@Override public T visitTraversalTLong(final GremlinParser.TraversalTLongContext ctx) { notImplemented(ctx); return null; }
1688+
/**
1689+
* {@inheritDoc}
1690+
*/
1691+
@Override public T visitTraversalDirectionShort(final GremlinParser.TraversalDirectionShortContext ctx) { notImplemented(ctx); return null; }
1692+
/**
1693+
* {@inheritDoc}
1694+
*/
1695+
@Override public T visitTraversalDirectionLong(final GremlinParser.TraversalDirectionLongContext ctx) { notImplemented(ctx); return null; }
1696+
/**
1697+
* {@inheritDoc}
1698+
*/
1699+
@Override public T visitGenericLiteralMapNullable(final GremlinParser.GenericLiteralMapNullableContext ctx) { notImplemented(ctx); return null; }
1700+
/**
1701+
* {@inheritDoc}
1702+
*/
1703+
@Override public T visitStringLiteralVarargsArgument(final GremlinParser.StringLiteralVarargsArgumentContext ctx) { notImplemented(ctx); return null; }
1704+
/**
1705+
* {@inheritDoc}
1706+
*/
1707+
@Override public T visitMapKey(final GremlinParser.MapKeyContext ctx) { notImplemented(ctx); return null; }
1708+
/**
1709+
* {@inheritDoc}
1710+
*/
1711+
@Override public T visitNakedKey(final GremlinParser.NakedKeyContext ctx) { notImplemented(ctx); return null;}
1712+
/**
1713+
* {@inheritDoc}
1714+
*/
1715+
@Override public T visitStructureVertexArgument(final GremlinParser.StructureVertexArgumentContext ctx) { notImplemented(ctx); return null; }
16841716
}

0 commit comments

Comments
 (0)