Lei Shu created TINKERPOP-3269:
----------------------------------
Summary: Invalid non-string predicate in where(P) throws an
internal ClassCastException instead of a validation error
Key: TINKERPOP-3269
URL: https://issues.apache.org/jira/browse/TINKERPOP-3269
Project: TinkerPop
Issue Type: New Feature
Reporter: Lei Shu
h3. TinkerPop version
Originally observed on:
{{Apache TinkerPop 3.7.0
Gremlin Server with TinkerGraph
Interface: WebSocket}}
Please note that the issue should also be retested on a currently maintained
release before triage.
h3. Environment
* Deployment: Docker
* Image: {{tinkerpop/gremlin-server}}
* Graph implementation: TinkerGraph
* Query language: Gremlin-Groovy
* Interface: Gremlin Server over WebSocket
h3. Description
Passing a predicate with a non-string value to {{where(P)}} causes an internal
{{ClassCastException}} in {{{}WherePredicateStep.getSelectKey(){}}}.
For example:
{{g.inject(10).where(gt(5)).fold()}}
fails with:
{{java.lang.ClassCastException:
class java.lang.Integer cannot be cast to class java.lang.String
at WherePredicateStep.getSelectKey(...)}}
{{where(P)}} uses the predicate value as the name of a path label, map key, or
side-effect binding. Therefore, {{where(gt(5))}} is not the correct way to test
whether the current scalar value is greater than {{{}5{}}}.
The correct scalar-filtering form is:
{{g.inject(10).is(gt(5)).fold()}}
which returns:
{{[10]}}
The invalid traversal may reasonably be rejected, but it should produce a
descriptive validation or argument error rather than exposing an internal Java
type cast.
h3. Minimal reproduction
{{g.inject(10).where(gt(5)).fold()}}
h3. Expected behavior
The traversal should be rejected with a descriptive error explaining that the
predicate value supplied to {{where(P)}} must identify a string scope key or
variable binding.
For example:
{{where(P) requires the predicate value to be a String scope key;
use is(P) to filter the current scalar value}}
The exact wording is not important, but the engine should not expose an
internal {{{}ClassCastException{}}}.
h3. Actual behavior
The traversal fails with an internal exception:
{{ClassCastException: Integer cannot be cast to String
at WherePredicateStep.getSelectKey(...)}}
h3. Additional reproduction through {{values()}}
{{g.V().drop().iterate()
g.addV('X').property('v', 10).iterate()
g.addV('X').property('v', 20).iterate()
g.V().
hasLabel('X').
where(__.values('v').where(gt(5))).
values('v').
fold()}}
Actual result:
{{ClassCastException: Integer cannot be cast to String}}
The equivalent valid traversal works:
{{g.V().
hasLabel('X').
where(__.values('v').is(gt(5))).
values('v').
fold()}}
Result:
{{[10, 20]}}
h3. Additional reproduction after {{select()}}
{{g.V().
hasLabel('X').
as('x').
where(
__.select('x').
values('v').
where(gt(5))
).
values('v').
fold()}}
Actual result:
{{ClassCastException: Integer cannot be cast to String}}
Valid form:
{{g.V().
hasLabel('X').
as('x').
where(
__.select('x').
values('v').
is(gt(5))
).
values('v').
fold()}}
Result:
{{[10, 20]}}
h3. Why this appears to be a bug
The traversal itself uses the wrong step for scalar filtering:
{{where(gt(5))}}
instead of:
{{is(gt(5))}}
However, the invalid predicate reaches
{{{}WherePredicateStep.getSelectKey(){}}}, where its integer value is cast
directly to {{{}String{}}}.
This exposes an internal implementation exception rather than reporting an
invalid {{where(P)}} argument.
The issue is therefore error validation and diagnostics, not incorrect
filtering semantics. {{where(P)}} does not need to support numeric literal
predicates, but it should reject them cleanly.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)