imbajin commented on code in PR #833:
URL:
https://github.com/apache/hugegraph-toolchain/pull/833#discussion_r4350132075
##########
hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/util/ReadOnlyGremlin.java:
##########
@@ -65,13 +143,183 @@ public static void validate(String query) {
if (!"V".equals(start) && !"E".equals(start)) {
throw invalid();
}
- parser.arguments(0);
- parser.chain(STEPS, 0);
+ List<Step> steps = new ArrayList<>();
+ steps.add(new Step(start, parser.arguments(0), 0));
+ parser.chain(STEPS.keySet(), 0, steps);
parser.consume(';');
parser.whitespace();
if (parser.position != query.length()) {
throw invalid();
}
+ return new Traversal(steps, query.length());
+ }
+
+ private enum Output {
+ PRESERVE, EXPAND, REDUCE, COLLECT, LIMIT, CONSUME
+ }
+
+ static final class Traversal {
+
+ private final List<Step> steps;
+ private final int endPosition;
+
+ private Traversal(List<Step> steps, int endPosition) {
+ this.steps = List.copyOf(steps);
+ this.endPosition = endPosition;
+ }
+
+ int limitPosition(boolean preview, int limit) {
+ // Preview limits include the sentinel row used to report
truncation.
+ BigInteger previewSize = BigInteger.valueOf((long) limit - 1);
+ Analysis result = this.analyze(previewSize);
+ if (preview && result.largeCollection) {
+ throw new
ExternalException("gremlin.preview.collection_requires_async", previewSize);
+ }
+ return !result.singleResult && (preview || result.bound == null) ?
result.position : -1;
+ }
+
+ private Analysis analyze(BigInteger previewSize) {
+ BigInteger bound = null;
+ boolean singleResult = false;
+ boolean largeCollection = false;
+ boolean nestedCollection = false;
+ int position = this.endPosition;
+ for (int i = 0; i < this.steps.size(); i++) {
+ Step step = this.steps.get(i);
+ switch (STEPS.get(step.name)) {
+ case CONSUME:
+ // Cap the traversal before its final consumer,
preserving
+ // the List/Set/value/boolean result type. Further
methods
+ // would operate on materialized results, outside this
grammar.
+ if (i != this.steps.size() - 1) {
+ return new Analysis(-1, bound, true, false);
+ }
+ position = step.dotPosition;
+ if ("hasNext".equals(step.name)) {
+ largeCollection = false;
+ nestedCollection = false;
+ }
+ break;
+ case EXPAND:
+ bound = null;
+ singleResult = false;
+ largeCollection = false;
+ break;
+ case REDUCE:
+ largeCollection = false;
+ nestedCollection = false;
+ if (!step.localScope()) {
+ bound = BigInteger.ONE;
+ singleResult = true;
+ }
+ break;
+ case COLLECT:
+ // The keyed group overloads accumulate a side effect
+ // while passing each input traverser through.
+ if (("group".equals(step.name) ||
"groupCount".equals(step.name)) &&
+ !step.arguments.isEmpty()) {
+ break;
+ }
+ if (!step.localScope()) {
+ // A single List/Map can still download an entire
+ // graph. A later outer limit cannot shrink its
input.
+ largeCollection |= bound == null ||
bound.compareTo(previewSize) > 0;
+ // group() values are collections; unfolding its
Map
+ // returns entries that retain those complete
values.
+ nestedCollection |= "group".equals(step.name) &&
largeCollection;
Review Comment:
P2: nested fold still bypasses the preview collection bound. At
99ba42d216f38141b61c928625f0db7ed87ac11e, g.V().fold().fold().unfold().limit(1)
is accepted: only group marks nestedCollection, and EXPAND/unfold clears
largeCollection even though one nested collection remains. Two independent
bounded probes compiled the exact parser and executed TinkerGraph3.8.1 fixtures
of1001 and1500 vertices. Each returned one List containing all fixture
vertices, even with the outer preview row limit; an input limit(10) control
returned10 values. This is a supported-grammar result-size bypass, not proof of
a production outage or a full Hubble deployment test. Track collection
nesting/provenance across collection and expansion steps; add paired
regressions for double-fold followed by one unfold, safe single-fold/unfold,
and bounded double-unfold. The separate WITH LIMIT frontend repair is verified
and should retain fix credit.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]