Skip to content

Commit

Permalink
TINKERPOP-3022 Fixed JavaTranslator issues with has(String,null)
Browse files Browse the repository at this point in the history
Needed to better handle defaults for has(String,Traversal) on the case where reflection in JavaTranslator chose that method for has(String,null). CTR
  • Loading branch information
spmallette committed Dec 14, 2023
1 parent b48fd8c commit 67b8a33
Show file tree
Hide file tree
Showing 7 changed files with 27 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
* Improved error message from `JavaTranslator` by including exception source.
* Added tests for error handling for GLV's if tx.commit() is called remotely for graphs without transactions support.
* Introduced multi-architecture AMD64/ARM64 docker images for gremlin-console.
* Fixed bug in `JavaTranslator` where `has(String, null)` could call `has(String, Traversal)` to generate an error.
[[release-3-6-6]]
=== TinkerPop 3.6.6 (November 20, 2023)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1564,6 +1564,11 @@ public default GraphTraversal<S, E> where(final Traversal<?, ?> whereTraversal)
* @since 3.0.0-incubating
*/
public default GraphTraversal<S, E> has(final String propertyKey, final P<?> predicate) {
// Groovy can get the overload wrong for has(T, null) which should probably go at has(T,Object). users could
// explicit cast but a redirect here makes this a bit more seamless
if (null == predicate)
return has(propertyKey, (Object) null);

this.asAdmin().getBytecode().addStep(Symbols.has, propertyKey, predicate);
return TraversalHelper.addHasContainer(this.asAdmin(), new HasContainer(propertyKey, predicate));
}
Expand Down Expand Up @@ -1710,6 +1715,13 @@ public default GraphTraversal<S, E> has(final T accessor, final Traversal<?, ?>
* @since 3.0.0-incubating
*/
public default GraphTraversal<S, E> has(final String propertyKey, final Traversal<?, ?> propertyTraversal) {
// the translation here of null to has(String, Object) is likely what was intended. a null Traversal doesn't
// really make much sense. this should resolve issues with JavaTranslator grabbing this method when bytecode
// uses null as the second argument. we've taken this tactic for other overloads of has() as well, so just
// continuing with that pattern.
if (null == propertyTraversal)
return has(propertyKey, (Object) null);

this.asAdmin().getBytecode().addStep(Symbols.has, propertyKey, propertyTraversal);
return this.asAdmin().addStep(
new TraversalFilterStep<>(this.asAdmin(), propertyTraversal.asAdmin().addStep(0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ private static IDictionary<string, List<Func<GraphTraversalSource, IDictionary<s
{"g_V_hasXlabel_personX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has(T.Label,"person")}},
{"g_V_hasXlabel_eqXpersonXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has(T.Label,P.Eq("person"))}},
{"g_V_hasXlabel_isXpersonXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has(T.Label,__.Is("person"))}},
{"g_V_hasXname_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("name",(object) null)}},
{"g_V_hasIdXemptyX_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasId(p["xx1"]).Count()}},
{"g_V_hasIdXwithinXemptyXX_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasId(p["xx1"]).Count()}},
{"g_V_hasIdXwithoutXemptyXX_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasId(p["xx1"]).Count()}},
Expand Down
1 change: 1 addition & 0 deletions gremlin-go/driver/cucumber/gremlin.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ var translationMap = map[string][]func(g *gremlingo.GraphTraversalSource, p map[
"g_V_hasXlabel_personX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has(gremlingo.T.Label, "person")}},
"g_V_hasXlabel_eqXpersonXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has(gremlingo.T.Label, gremlingo.P.Eq("person"))}},
"g_V_hasXlabel_isXpersonXX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has(gremlingo.T.Label, gremlingo.T__.Is("person"))}},
"g_V_hasXname_nullX": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Has("name", nil)}},
"g_V_hasIdXemptyX_count": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasId(p["xx1"]).Count()}},
"g_V_hasIdXwithinXemptyXX_count": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasId(p["xx1"]).Count()}},
"g_V_hasIdXwithoutXemptyXX_count": {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) *gremlingo.GraphTraversal {return g.V().HasId(p["xx1"]).Count()}},
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions gremlin-python/src/main/python/radish/gremlin.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@
'g_V_hasXlabel_personX': [(lambda g:g.V().has(T.label,'person'))],
'g_V_hasXlabel_eqXpersonXX': [(lambda g:g.V().has(T.label,P.eq('person')))],
'g_V_hasXlabel_isXpersonXX': [(lambda g:g.V().has(T.label,__.is_('person')))],
'g_V_hasXname_nullX': [(lambda g:g.V().has('name',None))],
'g_V_hasIdXemptyX_count': [(lambda g, xx1=None:g.V().hasId(xx1).count())],
'g_V_hasIdXwithinXemptyXX_count': [(lambda g, xx1=None:g.V().hasId(xx1).count())],
'g_V_hasIdXwithoutXemptyXX_count': [(lambda g, xx1=None:g.V().hasId(xx1).count())],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -611,4 +611,13 @@ Feature: Step - has()
| v[marko] |
| v[vadas] |
| v[josh] |
| v[peter] |
| v[peter] |

Scenario: g_V_hasXname_nullX
Given the modern graph
And the traversal of
"""
g.V().has("name", null)
"""
When iterated to list
Then the result should be empty

0 comments on commit 67b8a33

Please sign in to comment.