Coverage Summary for Class: TestPropertyValues (org.umlg.sqlg.test.properties)
Class |
Class, %
|
Method, %
|
Branch, %
|
Line, %
|
TestPropertyValues |
100%
(1/1)
|
100%
(21/21)
|
88.2%
(30/34)
|
100%
(342/342)
|
package org.umlg.sqlg.test.properties;
import org.apache.tinkerpop.gremlin.process.traversal.Order;
import org.apache.tinkerpop.gremlin.process.traversal.Step;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.IdStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectOneStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.IdentityStep;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;
import org.umlg.sqlg.sql.parse.ReplacedStep;
import org.umlg.sqlg.step.SqlgGraphStep;
import org.umlg.sqlg.step.SqlgPropertiesStep;
import org.umlg.sqlg.step.SqlgVertexStep;
import org.umlg.sqlg.structure.SqlgElement;
import org.umlg.sqlg.test.BaseTest;
import java.util.*;
/**
* test behavior on property values
*
* @author JP Moresmau
* @author <a href="https://github.com/pietermartin">Pieter Martin</a>
*/
public class TestPropertyValues extends BaseTest {
@Test
public void testRestrictedProperties() {
loadModern();
List<Map<Object, Object>> results = this.sqlgGraph.traversal().V().hasLabel("person").as("p")
.out("created")
.group()
.by("name")
.by(__.select("p").values("age").sum())
.toList();
// When iterated to list
// Then the result should be unordered
// | result |
// | m[{"ripple":"d[32].l", "lop":"d[96].l"}] |
Assert.assertEquals(1, results.size());
Assert.assertTrue(results.get(0).containsKey("ripple"));
Assert.assertEquals(32L, results.get(0).get("ripple"));
Assert.assertTrue(results.get(0).containsKey("lop"));
Assert.assertEquals(96L, results.get(0).get("lop"));
}
@Test
public void testRestrictedPropertiesAfterCache() {
Assume.assumeTrue(isPostgres());
this.sqlgGraph.addVertex(T.label, "A", "name", "john", "surname", "smith");
this.sqlgGraph.tx().commit();
GraphTraversal<Vertex, String> namesTraversal = this.sqlgGraph.traversal().V().hasLabel("A").<String>values("name");
String nameSql = getSQL(namesTraversal);
Assert.assertEquals("SELECT\n" +
"\t\"public\".\"V_A\".\"ID\" AS \"alias1\",\n" +
"\t\"public\".\"V_A\".\"name\" AS \"alias2\"\n" +
"FROM\n" +
"\t\"public\".\"V_A\"", nameSql);
List<String> names = namesTraversal.toList();
Assert.assertEquals(1, names.size());
Assert.assertEquals("john", names.get(0));
GraphTraversal<Vertex, String> surnameTraversal = this.sqlgGraph.traversal().V().hasLabel("A").<String>values("surname");
String surnameSql = getSQL(surnameTraversal);
Assert.assertEquals("SELECT\n" +
"\t\"public\".\"V_A\".\"ID\" AS \"alias1\",\n" +
"\t\"public\".\"V_A\".\"surname\" AS \"alias2\"\n" +
"FROM\n" +
"\t\"public\".\"V_A\"", surnameSql);
List<String> surnames = surnameTraversal.toList();
Assert.assertEquals(1, surnames.size());
Assert.assertEquals("smith", surnames.get(0));
}
@Test
public void testSelectFollowedByValues() {
Vertex a1 = this.sqlgGraph.addVertex(T.label, "A", "name", "a1");
Vertex a2 = this.sqlgGraph.addVertex(T.label, "A", "name", "a2");
Vertex b1 = this.sqlgGraph.addVertex(T.label, "B", "name", "b1");
Vertex b2 = this.sqlgGraph.addVertex(T.label, "B", "name", "b2");
Vertex c1 = this.sqlgGraph.addVertex(T.label, "C", "xxxx", "c1", "yyyy", "y1", "zzzz", "z1");
Vertex c2 = this.sqlgGraph.addVertex(T.label, "C", "xxxx", "c2", "yyyy", "y2", "zzzz", "z2");
Vertex d1 = this.sqlgGraph.addVertex(T.label, "D", "name", "d1");
Vertex d2 = this.sqlgGraph.addVertex(T.label, "D", "name", "d2");
a1.addEdge("ab", b1);
a2.addEdge("ab", b2);
b1.addEdge("bc", c1);
b2.addEdge("bc", c2);
c1.addEdge("cd", d1);
c2.addEdge("cd", d2);
this.sqlgGraph.tx().commit();
DefaultGraphTraversal<Vertex, String> traversal = (DefaultGraphTraversal<Vertex, String>) this.sqlgGraph.traversal().V()
.hasLabel("C")
.has("yyyy", "y1")
.as("c")
.in("bc")
.in("ab")
.has("name", "a1")
.as("a")
.<Vertex>select("a", "c")
.select("c")
.<String>values("xxxx");
printTraversalForm(traversal);
Assert.assertEquals(6, traversal.getSteps().size());
Assert.assertTrue(traversal.getSteps().get(0) instanceof SqlgGraphStep);
Assert.assertTrue(traversal.getSteps().get(1) instanceof IdentityStep);
Assert.assertTrue(traversal.getSteps().get(2) instanceof IdentityStep);
Assert.assertTrue(traversal.getSteps().get(3) instanceof SelectStep);
Assert.assertTrue(traversal.getSteps().get(4) instanceof SelectOneStep);
Assert.assertTrue(traversal.getSteps().get(5) instanceof SqlgPropertiesStep);
List<String> names = traversal.toList();
Assert.assertEquals(1, names.size());
Assert.assertEquals("c1", names.get(0));
checkRestrictedProperties(SqlgGraphStep.class, traversal, 0, "xxxx");
}
@Test
public void testSelectOneFollowedByValues() {
Vertex a1 = this.sqlgGraph.addVertex(T.label, "A", "name", "a1");
Vertex a2 = this.sqlgGraph.addVertex(T.label, "A", "name", "a2");
Vertex b1 = this.sqlgGraph.addVertex(T.label, "B", "name", "b1");
Vertex b2 = this.sqlgGraph.addVertex(T.label, "B", "name", "b2");
Vertex c1 = this.sqlgGraph.addVertex(T.label, "C", "xxxx", "c1", "yyyy", "y1", "zzzz", "z1");
Vertex c2 = this.sqlgGraph.addVertex(T.label, "C", "xxxx", "c2", "yyyy", "y2", "zzzz", "z2");
Vertex d1 = this.sqlgGraph.addVertex(T.label, "D", "name", "d1");
Vertex d2 = this.sqlgGraph.addVertex(T.label, "D", "name", "d2");
a1.addEdge("ab", b1);
a2.addEdge("ab", b2);
b1.addEdge("bc", c1);
b2.addEdge("bc", c2);
c1.addEdge("cd", d1);
c2.addEdge("cd", d2);
this.sqlgGraph.tx().commit();
DefaultGraphTraversal<Vertex, String> traversal = (DefaultGraphTraversal<Vertex, String>) this.sqlgGraph.traversal().V()
.hasLabel("C")
.has("yyyy", "y1")
.as("c")
.in("bc")
.in("ab")
.has("name", "a1")
.<Vertex>select("c")
.<String>values("xxxx");
printTraversalForm(traversal);
Assert.assertEquals(4, traversal.getSteps().size());
Assert.assertTrue(traversal.getSteps().get(0) instanceof SqlgGraphStep);
Assert.assertTrue(traversal.getSteps().get(1) instanceof IdentityStep);
Assert.assertTrue(traversal.getSteps().get(2) instanceof SelectOneStep);
Assert.assertTrue(traversal.getSteps().get(3) instanceof SqlgPropertiesStep);
List<String> names = traversal.toList();
Assert.assertEquals(1, names.size());
Assert.assertEquals("c1", names.get(0));
checkRestrictedProperties(SqlgGraphStep.class, traversal, 0, "xxxx");
}
@Test
public void testOptimizePastSelect() {
Vertex a1 = this.sqlgGraph.addVertex(T.label, "A", "name", "a1");
Vertex a2 = this.sqlgGraph.addVertex(T.label, "A", "name", "a2");
Vertex b1 = this.sqlgGraph.addVertex(T.label, "B", "name", "b1");
Vertex b2 = this.sqlgGraph.addVertex(T.label, "B", "name", "b2");
Vertex c1 = this.sqlgGraph.addVertex(T.label, "C", "name", "c1");
Vertex c2 = this.sqlgGraph.addVertex(T.label, "C", "name", "c2");
Vertex d1 = this.sqlgGraph.addVertex(T.label, "D", "name", "d1", "surname", "s1");
Vertex d2 = this.sqlgGraph.addVertex(T.label, "D", "name", "d2", "surname", "s2");
a1.addEdge("ab", b1);
a2.addEdge("ab", b2);
b1.addEdge("bc", c1);
b2.addEdge("bc", c2);
c1.addEdge("cd", d1);
c2.addEdge("cd", d2);
this.sqlgGraph.tx().commit();
Traversal<Vertex, String> traversal = this.sqlgGraph.traversal()
.V().hasLabel("C")
.has("name", "c2")
.as("c")
.in("bc")
.in("ab")
.has("name", "a2")
.select("c")
.out("cd")
.has("name", "d2")
.values("surname");
printTraversalForm(traversal);
List<String> surnames = traversal.toList();
Assert.assertEquals(1, surnames.size());
Assert.assertEquals("s2", surnames.get(0));
checkRestrictedProperties(SqlgVertexStep.class, traversal, 0, "surname");
}
@Test
public void testMultipleSelect() {
Vertex vA = sqlgGraph.addVertex(T.label, "A", "name", "root");
Vertex vI = sqlgGraph.addVertex(T.label, "I", "name", "item1");
vA.addEdge("likes", vI, "howMuch", 5, "who", "Joe");
this.sqlgGraph.tx().commit();
Object id0 = vI.id();
DefaultGraphTraversal<Vertex, Map<String, Object>> traversal = (DefaultGraphTraversal<Vertex, Map<String, Object>>) sqlgGraph.traversal().V()
.hasLabel("A")
.has("name", "root")
.outE("likes")
.as("e")
.values("howMuch").as("stars")
.select("e")
.values("who").as("user")
.select("e")
.inV()
.id().as("item")
.select("user", "stars", "item");
printTraversalForm(traversal);
Assert.assertEquals(8, traversal.getSteps().size());
Assert.assertTrue(traversal.getSteps().get(0) instanceof SqlgGraphStep<?, ?>);
Assert.assertTrue(traversal.getSteps().get(1) instanceof SqlgPropertiesStep<?>);
Assert.assertTrue(traversal.getSteps().get(2) instanceof SelectOneStep<?, ?>);
Assert.assertTrue(traversal.getSteps().get(3) instanceof SqlgPropertiesStep<?>);
Assert.assertTrue(traversal.getSteps().get(4) instanceof SelectOneStep<?, ?>);
Assert.assertTrue(traversal.getSteps().get(5) instanceof SqlgVertexStep<?>);
Assert.assertTrue(traversal.getSteps().get(6) instanceof IdStep<?>);
Assert.assertTrue(traversal.getSteps().get(7) instanceof SelectStep<?, ?>);
Assert.assertTrue(traversal.hasNext());
Map<String, Object> m = traversal.next();
Assert.assertEquals(5, m.get("stars"));
Assert.assertEquals("Joe", m.get("user"));
Assert.assertEquals(id0, m.get("item"));
}
/**
* If the order() does not happen on the database, i.e. in java code then the property also needs to be present.
*/
@Test
public void testInMemoryOrderByValues() {
loadModern();
final Traversal<Vertex, String> traversal = this.sqlgGraph.traversal().V().both().hasLabel("person").order().by("age", Order.desc).limit(5).values("name");
printTraversalForm(traversal);
checkOrderedResults(Arrays.asList("peter", "josh", "josh", "josh", "marko"), traversal);
}
@Test
public void testValueMapOneObject() {
loadModern();
final Traversal<Vertex, Map<Object, Object>> traversal = sqlgGraph.traversal().V().hasLabel("person").valueMap("name");
checkColumnsNotPresent(traversal, "age");
checkRestrictedProperties(SqlgGraphStep.class, traversal, 0, "name");
Set<String> names = new HashSet<>();
while (traversal.hasNext()) {
Map<Object, Object> m = traversal.next();
Assert.assertNotNull(m);
Assert.assertEquals(1, m.size());
Assert.assertTrue(m.containsKey("name"));
Object v = m.get("name");
// "It is important to note that the map of a vertex maintains a list of values for each key."
Assert.assertTrue(v instanceof List<?>);
List<?> l = (List<?>) v;
Assert.assertEquals(1, l.size());
Object v1 = l.get(0);
Assert.assertTrue(v1 instanceof String);
names.add((String) v1);
}
Assert.assertEquals(new HashSet<>(Arrays.asList("marko", "vadas", "josh", "peter")), names);
}
@Test
public void testValueMapAllObject() {
loadModern();
final Traversal<Vertex, Map<Object, Object>> traversal = sqlgGraph.traversal().V().hasLabel("person").valueMap();
printTraversalForm(traversal);
checkNoRestrictedProperties(traversal);
Set<String> names = new HashSet<>();
Set<Integer> ages = new HashSet<>();
while (traversal.hasNext()) {
Map<Object, Object> m = traversal.next();
Assert.assertNotNull(m);
Assert.assertEquals(2, m.size());
Assert.assertTrue(m.containsKey("name"));
Object v = m.get("name");
// "It is important to note that the map of a vertex maintains a list of values for each key."
Assert.assertTrue(v instanceof List<?>);
List<?> l = (List<?>) v;
Assert.assertEquals(1, l.size());
Object v1 = l.get(0);
Assert.assertTrue(v1 instanceof String);
names.add((String) v1);
Assert.assertTrue(m.containsKey("age"));
v = m.get("age");
// "It is important to note that the map of a vertex maintains a list of values for each key."
Assert.assertTrue(v instanceof List<?>);
l = (List<?>) v;
Assert.assertEquals(1, l.size());
v1 = l.get(0);
Assert.assertTrue(v1 instanceof Integer);
ages.add((Integer) v1);
}
Assert.assertEquals(new HashSet<>(Arrays.asList("marko", "vadas", "josh", "peter")), names);
Assert.assertEquals(new HashSet<>(Arrays.asList(29, 27, 32, 35)), ages);
}
@SuppressWarnings("unchecked")
@Test
public void testValueMapAliasVertex() {
loadModern();
final Traversal<Vertex, Map<String, Object>> traversal = sqlgGraph.traversal()
.V().hasLabel("person").as("a")
.valueMap("name").as("b")
.select("a", "b");
printTraversalForm(traversal);
checkNoRestrictedProperties(traversal);
Set<String> names1 = new HashSet<>();
Set<String> names2 = new HashSet<>();
Set<Integer> ages = new HashSet<>();
while (traversal.hasNext()) {
Map<String, Object> m = traversal.next();
Assert.assertNotNull(m);
Assert.assertEquals(2, m.size());
Assert.assertTrue(m.containsKey("a"));
Assert.assertTrue(m.containsKey("b"));
Vertex v = (Vertex) m.get("a");
Assert.assertNotNull(v.property("name").value());
Assert.assertNotNull(v.property("age").value());
names1.add((String) v.property("name").value());
ages.add((Integer) v.property("age").value());
Map<String, Object> m2 = (Map<String, Object>) m.get("b");
Object o = m2.get("name");
// "It is important to note that the map of a vertex maintains a list of values for each key."
Assert.assertTrue(o instanceof List<?>);
List<?> l = (List<?>) o;
Assert.assertEquals(1, l.size());
Object v1 = l.get(0);
Assert.assertTrue(v1 instanceof String);
names2.add((String) v1);
}
Assert.assertEquals(names1, names2);
Assert.assertEquals(new HashSet<>(Arrays.asList("marko", "vadas", "josh", "peter")), names1);
Assert.assertEquals(new HashSet<>(Arrays.asList(29, 27, 32, 35)), ages);
}
@Test
public void testValuesOne() {
loadModern();
final Traversal<Vertex, String> traversal = sqlgGraph.traversal().V().hasLabel("person").values("name");
checkColumnsNotPresent(traversal, "age");
checkRestrictedProperties(SqlgGraphStep.class, traversal, 0, "name");
Set<String> names = new HashSet<>();
while (traversal.hasNext()) {
names.add(traversal.next());
}
Assert.assertEquals(new HashSet<>(Arrays.asList("marko", "vadas", "josh", "peter")), names);
}
@Test
public void testValuesAll() {
loadModern();
final Traversal<Vertex, Object> traversal = sqlgGraph.traversal().V().hasLabel("person").values();
printTraversalForm(traversal);
checkNoRestrictedProperties(traversal);
Set<Object> values = new HashSet<>();
while (traversal.hasNext()) {
values.add(traversal.next());
}
Assert.assertEquals(new HashSet<>(Arrays.asList("marko", "vadas", "josh", "peter", 29, 27, 32, 35)), values);
}
@Test
public void testValuesOneWhere() {
loadModern();
final Traversal<Vertex, String> traversal = sqlgGraph.traversal().V().hasLabel("person").has("age", 29).values("name");
checkColumnsNotPresent(traversal, "age");
checkRestrictedProperties(SqlgGraphStep.class, traversal, 0, "name");
Set<String> names = new HashSet<>();
while (traversal.hasNext()) {
names.add(traversal.next());
}
Assert.assertEquals(new HashSet<>(Arrays.asList("marko")), names);
}
@Test
public void g_V_hasLabelXpersonX_order_byXageX_skipX1X_valuesXnameX() {
loadModern();
// final Traversal<Vertex, String> traversal = this.sqlgGraph.traversal()
// .V().hasLabel("person")
// .order().by("age")
// .skip(1)
// .values("name");
final Traversal<Vertex, String> traversal = this.sqlgGraph.traversal()
.V().hasLabel("person")
.order().by("age")
.<String>values("name")
.skip(1);
// .values("name");
printTraversalForm(traversal);
// name because explicitly requested, age because we order on it
checkRestrictedProperties(SqlgGraphStep.class, traversal, 0, "name", "age");
Assert.assertTrue(traversal.hasNext());
Assert.assertEquals(Arrays.asList("marko", "josh", "peter"), traversal.toList());
}
@Test
public void testOut() {
loadModern();
final Traversal<Vertex, String> traversal = this.sqlgGraph.traversal()
.V().hasLabel("person")
.out("created")
.values("name");
checkColumnsNotPresent(traversal, "language");
checkRestrictedProperties(SqlgGraphStep.class, traversal, 1, "name");
Set<String> names = new HashSet<>();
while (traversal.hasNext()) {
names.add(traversal.next());
}
Assert.assertEquals(new HashSet<>(Arrays.asList("lop", "ripple")), names);
}
@Test
public void g_V_both_name_order_byXa_bX_dedup_value() {
loadModern();
@SuppressWarnings("ComparatorCombinators") final Traversal<Vertex, String> traversal = this.sqlgGraph.traversal()
.V()
.both()
.<String>properties("name")
.order().by((a, b) -> a.value().compareTo(b.value()))
.dedup().value();
printTraversalForm(traversal);
final List<String> names = traversal.toList();
Assert.assertEquals(6, names.size());
Assert.assertEquals("josh", names.get(0));
Assert.assertEquals("lop", names.get(1));
Assert.assertEquals("marko", names.get(2));
Assert.assertEquals("peter", names.get(3));
Assert.assertEquals("ripple", names.get(4));
Assert.assertEquals("vadas", names.get(5));
Assert.assertFalse(traversal.hasNext());
}
@Test
public void g_V_valuesXnameX_order_tail() {
loadModern();
final Traversal<Vertex, String> traversal = this.sqlgGraph.traversal().V().<String>values("name").order().tail();
printTraversalForm(traversal);
Assert.assertEquals(List.of("vadas"), traversal.toList());
}
/**
* check provided columns/properties are not selected in the SQL
*
* @param t the traversal
* @param properties the properties to check for absence
*/
private void checkColumnsNotPresent(Traversal<?, ?> t, String... properties) {
String sql = getSQL(t);
Assert.assertNotNull(sql);
sql = sql.trim();
Assert.assertTrue(sql.startsWith("SELECT"));
int ix = sql.indexOf("FROM");
Assert.assertTrue(ix > 0);
String select = sql.substring(0, ix);
for (String p : properties) {
Assert.assertFalse(select.contains(p));
}
}
/**
* check the replaced steps has the specified restricted properties
*
* @param t the traversal
* @param properties the properties
*/
@SuppressWarnings({"resource", "unchecked"})
public static void checkRestrictedProperties(Class<? extends Step> stepType, Traversal<?, ?> t, int replacedStepCount, String... properties) {
boolean found = false;
for (Step<?, ?> s : ((Traversal.Admin<?, ?>) t).getSteps()) {
if (stepType == SqlgGraphStep.class && s instanceof SqlgGraphStep) {
SqlgGraphStep<?, SqlgElement> gs = (SqlgGraphStep<?, SqlgElement>) s;
ReplacedStep<?, ?> rs = gs.getReplacedSteps().get(replacedStepCount);
Assert.assertEquals(new HashSet<>(Arrays.asList(properties)), rs.getRestrictedProperties());
found = true;
} else if (stepType == SqlgVertexStep.class && s instanceof SqlgVertexStep) {
SqlgVertexStep<SqlgElement> gs = (SqlgVertexStep<SqlgElement>) s;
ReplacedStep<?, ?> rs = gs.getReplacedSteps().get(gs.getReplacedSteps().size() - 1);
Assert.assertEquals(new HashSet<>(Arrays.asList(properties)), rs.getRestrictedProperties());
found = true;
}
if (found) {
break;
}
}
Assert.assertTrue(found);
}
/**
* check the replaced steps has the specified restricted properties
*
* @param t the traversal, EVALUATED (ie call printTraversalForm or getSQL first)
*/
@SuppressWarnings({"resource", "unchecked"})
private void checkNoRestrictedProperties(Traversal<?, ?> t) {
boolean found = false;
for (Step<?, ?> s : ((Traversal.Admin<?, ?>) t).getSteps()) {
if (s instanceof SqlgGraphStep) {
SqlgGraphStep<?, SqlgElement> gs = (SqlgGraphStep<?, SqlgElement>) s;
ReplacedStep<?, ?> rs = gs.getReplacedSteps().get(gs.getReplacedSteps().size() - 1);
Assert.assertNull(String.valueOf(rs.getRestrictedProperties()), rs.getRestrictedProperties());
found = true;
}
}
Assert.assertTrue(found);
}
}