Skip to content

Commit 12e527b

Browse files
committed
Preserve BulkSet in P
Doesn't address all the problems here with performance but for now just trying to preserve BulkSet for within/without which can happen with: aggregate('x')...where(without('x')) CTR
1 parent 766c70a commit 12e527b

File tree

3 files changed

+134
-3
lines changed

3 files changed

+134
-3
lines changed

CHANGELOG.asciidoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
2525
2626
This release also includes changes from <<release-3-7-6, 3.7.6>>.
2727
28+
* Preserved `BulkSet` when given to 'P'.
2829
* Fixed bug in Gremlin orderability semantics for `OffsetDateTime`.
2930
* Fixed bug in Javascript translation for UUID.
3031
* Fixed bug in pre-repeat() `emit()/until()` where `emit()` and `until()` traversers weren't added to the results.

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import org.apache.commons.collections.CollectionUtils;
2222
import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
23+
import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
2324
import org.apache.tinkerpop.gremlin.process.traversal.util.AndP;
2425
import org.apache.tinkerpop.gremlin.process.traversal.util.OrP;
2526

@@ -71,7 +72,12 @@ public P(final PBiPredicate<V, V> biPredicate, final GValue<V> value) {
7172
protected P(final PBiPredicate<V, V> biPredicate, final Collection<V> literals, final Map<String, V> variables, final boolean isCollection) {
7273
this.biPredicate = biPredicate;
7374
this.variables.putAll(variables);
74-
this.literals = new ArrayList<>(literals);
75+
if (literals instanceof BulkSet) {
76+
this.literals = new BulkSet<>();
77+
this.literals.addAll(literals);
78+
} else {
79+
this.literals = new ArrayList<>(literals);
80+
}
7581
this.isCollection = isCollection;
7682
}
7783

@@ -89,7 +95,16 @@ public PBiPredicate<V, V> getBiPredicate() {
8995
*/
9096
public V getValue() {
9197
if (isCollection) {
92-
Collection<V> values = this.literals.stream().collect(Collectors.toList());
98+
if (this.variables.isEmpty()) return (V) this.literals;
99+
100+
final Collection<V> values;
101+
if (this.literals instanceof BulkSet) {
102+
values = new BulkSet<>();
103+
values.addAll(this.literals);
104+
} else {
105+
values = new ArrayList<>(this.literals);
106+
}
107+
93108
values.addAll(this.variables.values());
94109
return (V) values;
95110
} else if (!this.literals.isEmpty()) {
@@ -113,7 +128,7 @@ public void setValue(final V value) {
113128
} else if (value instanceof Collection) {
114129
isCollection = true;
115130
if (((Collection<?>) value).stream().anyMatch(v -> v instanceof GValue)) {
116-
this.literals = new ArrayList<>();
131+
this.literals = (value instanceof BulkSet) ? new BulkSet<>() : new ArrayList<>();
117132
for (Object v : ((Collection<?>) value)) {
118133
// Separate variables and literals
119134
if (v instanceof GValue) {
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.tinkerpop.gremlin.process.traversal;
20+
21+
import org.apache.tinkerpop.gremlin.process.traversal.step.GValue;
22+
import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
23+
import org.junit.Test;
24+
25+
import java.util.Collection;
26+
import java.util.Collections;
27+
import java.util.Map;
28+
29+
import static org.junit.Assert.assertEquals;
30+
import static org.junit.Assert.assertTrue;
31+
32+
/**
33+
* Test class for {@link P} with {@link BulkSet} literals ensure that if a {@link BulkSet} is used as a literal,
34+
* it is preserved in the {@link P} object's value, and that the {@link P} object can handle {@link BulkSet} literals
35+
* with {@link GValue} elements correctly. You get a {@link BulkSet} in {@link P} when you have some Gremlin like:
36+
* {@code aggreate('x')...where(within('x'))}.
37+
*/
38+
public class PBulkSetTest {
39+
40+
@Test
41+
public void shouldPreserveBulkSetInGetValue() {
42+
final BulkSet<String> bulkSet = new BulkSet<>();
43+
bulkSet.add("a", 2);
44+
bulkSet.add("b", 1);
45+
46+
final P p = P.within(bulkSet);
47+
final Object value = p.getValue();
48+
49+
assertTrue("Value should be a BulkSet but was " + value.getClass().getName(), value instanceof BulkSet);
50+
assertEquals(bulkSet, value);
51+
assertEquals(3, ((BulkSet) value).size());
52+
assertEquals(2L, ((BulkSet) value).get("a"));
53+
}
54+
55+
@Test
56+
public void shouldPreserveBulkSetInSetValueWithGValues() {
57+
final BulkSet<Object> bulkSet = new BulkSet<>();
58+
bulkSet.add("a", 2);
59+
bulkSet.add(GValue.of("x", "b"), 1);
60+
61+
final P p = P.within(Collections.emptyList());
62+
p.setValue(bulkSet);
63+
64+
final Object value = p.getValue();
65+
// Currently this will fail and return an ArrayList (or a List from the stream)
66+
assertTrue("Value should be a BulkSet but was " + (value == null ? "null" : value.getClass().getName()), value instanceof BulkSet);
67+
assertEquals(3, ((BulkSet) value).size());
68+
assertEquals(2L, ((BulkSet) value).get("a"));
69+
}
70+
71+
@Test
72+
public void shouldCloneBulkSetInGetValueWithVariables() {
73+
final BulkSet<Object> bulkSet = new BulkSet<>();
74+
bulkSet.add("a", 2);
75+
76+
// Subclass to access protected constructor and merge literals and variables
77+
final P p = new PSubWithVars(Compare.eq, bulkSet, Collections.singletonMap("var1", "b"));
78+
79+
final Object value = p.getValue();
80+
assertTrue("Value should be a BulkSet but was " + (value == null ? "null" : value.getClass().getName()), value instanceof BulkSet);
81+
assertEquals(3, ((BulkSet) value).size());
82+
assertEquals(2L, ((BulkSet) value).get("a"));
83+
assertEquals(1L, ((BulkSet) value).get("b"));
84+
85+
// Ensure original bulkSet was not modified (p.getValue() should have cloned)
86+
assertEquals(2, bulkSet.size());
87+
assertEquals(2L, bulkSet.get("a"));
88+
assertEquals(0L, bulkSet.get("b"));
89+
}
90+
91+
@Test
92+
public void shouldPreserveBulkSetInProtectedConstructor() throws Exception {
93+
final BulkSet<String> bulkSet = new BulkSet<>();
94+
bulkSet.add("a", 2);
95+
96+
final P p = new PSub(Compare.eq, bulkSet);
97+
98+
final Object value = p.getValue();
99+
assertTrue("Value should be a BulkSet but was " + (value == null ? "null" : value.getClass().getName()), value instanceof BulkSet);
100+
assertEquals(2, ((BulkSet) value).size());
101+
assertEquals(2L, ((BulkSet) value).get("a"));
102+
}
103+
104+
private static class PSub extends P {
105+
public PSub(final PBiPredicate biPredicate, final Collection literals) {
106+
super(biPredicate, literals, Collections.emptyMap(), true);
107+
}
108+
}
109+
110+
private static class PSubWithVars extends P {
111+
public PSubWithVars(final PBiPredicate biPredicate, final Collection literals, final Map variables) {
112+
super(biPredicate, literals, variables, true);
113+
}
114+
}
115+
}

0 commit comments

Comments
 (0)