Coverage Summary for Class: TestForeignSchema (org.umlg.sqlg.test.topology)
Class |
Method, %
|
Branch, %
|
Line, %
|
TestForeignSchema |
100%
(24/24)
|
46.7%
(49/105)
|
97.7%
(669/685)
|
TestForeignSchema$1 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$10 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$11 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$12 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$13 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$14 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$15 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$16 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$17 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$18 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$19 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$2 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$20 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$21 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$22 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$23 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$24 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$25 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$26 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$27 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$28 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$29 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$3 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$30 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$31 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$32 |
100%
(1/1)
|
100%
(3/3)
|
TestForeignSchema$33 |
100%
(1/1)
|
100%
(3/3)
|
TestForeignSchema$34 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$35 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$36 |
100%
(1/1)
|
100%
(3/3)
|
TestForeignSchema$37 |
100%
(1/1)
|
100%
(3/3)
|
TestForeignSchema$38 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$4 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$5 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$6 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$7 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$8 |
100%
(1/1)
|
100%
(2/2)
|
TestForeignSchema$9 |
100%
(1/1)
|
100%
(2/2)
|
Total |
100%
(62/62)
|
46.7%
(49/105)
|
97.9%
(749/765)
|
package org.umlg.sqlg.test.topology;
import org.apache.commons.collections4.set.ListOrderedSet;
import org.apache.commons.configuration2.builder.fluent.Configurations;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.lang3.time.StopWatch;
import org.apache.tinkerpop.gremlin.process.traversal.Order;
import org.apache.tinkerpop.gremlin.process.traversal.P;
import org.apache.tinkerpop.gremlin.process.traversal.Scope;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Transaction;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.junit.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.umlg.sqlg.structure.PropertyDefinition;
import org.umlg.sqlg.structure.PropertyType;
import org.umlg.sqlg.structure.SqlgGraph;
import org.umlg.sqlg.structure.topology.EdgeLabel;
import org.umlg.sqlg.structure.topology.PropertyColumn;
import org.umlg.sqlg.structure.topology.Schema;
import org.umlg.sqlg.structure.topology.VertexLabel;
import org.umlg.sqlg.test.BaseTest;
import org.umlg.sqlg.util.SqlgUtil;
import java.net.URL;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@SuppressWarnings({"DuplicatedCode"})
public class TestForeignSchema extends BaseTest {
private final static Logger LOGGER = LoggerFactory.getLogger(TestForeignSchema.class);
private SqlgGraph sqlgGraphFdw;
@BeforeClass
public static void beforeClass() {
URL sqlProperties = Thread.currentThread().getContextClassLoader().getResource("sqlg.properties");
try {
Configurations configs = new Configurations();
configuration = configs.properties(sqlProperties);
Assume.assumeTrue(isPostgres());
configuration.addProperty("distributed", true);
if (!configuration.containsKey("jdbc.url"))
throw new IllegalArgumentException(String.format("SqlGraph configuration requires that the %s be set", "jdbc.url"));
} catch (ConfigurationException e) {
throw new RuntimeException(e);
}
}
@AfterClass
public static void afterClass() throws SQLException {
if (isPostgres()) {
URL sqlProperties = Thread.currentThread().getContextClassLoader().getResource("sqlg.properties");
try {
Configurations configs = new Configurations();
configuration = configs.properties(sqlProperties);
SqlgGraph sqlgGraph = SqlgGraph.open(configuration);
Connection connection = sqlgGraph.tx().getConnection();
try (Statement statement = connection.createStatement()) {
statement.execute("DROP SERVER IF EXISTS sqlgraph_fwd_server CASCADE;");
}
sqlgGraph.tx().commit();
} catch (ConfigurationException e) {
throw new RuntimeException(e);
}
}
}
@Before
public void before() throws Exception {
Assume.assumeTrue(isPostgres());
StopWatch stopWatch = new StopWatch();
stopWatch.start();
this.sqlgGraph = SqlgGraph.open(configuration);
SqlgUtil.dropDb(this.sqlgGraph);
Connection connection = this.sqlgGraph.tx().getConnection();
try (Statement statement = connection.createStatement()) {
for (String table : List.of("V_A", "V_B", "E_ab", "E_ba",
"V_person", "V_software", "E_created", "E_knows",
"V_song", "V_artist", "E_followedBy", "E_writtenBy", "E_sungBy")) {
String sql = String.format(
"DROP FOREIGN TABLE IF EXISTS \"%s\" CASCADE;",
table
);
statement.execute(sql);
}
String sql = String.format(
"DROP SCHEMA IF EXISTS \"%s\" CASCADE;",
"B"
);
statement.execute(sql);
}
this.sqlgGraph.tx().commit();
this.sqlgGraph.close();
this.sqlgGraph = SqlgGraph.open(configuration);
this.sqlgGraphFdw = SqlgGraph.open("sqlg.fdw.properties");
SqlgUtil.dropDb(this.sqlgGraphFdw);
this.sqlgGraphFdw.tx().commit();
this.sqlgGraphFdw.close();
this.sqlgGraphFdw = SqlgGraph.open("sqlg.fdw.properties");
grantReadOnlyUserPrivileges();
assertNotNull(this.sqlgGraph);
assertNotNull(this.sqlgGraph.getBuildVersion());
this.gt = this.sqlgGraph.traversal();
if (configuration.getBoolean("distributed", false)) {
this.sqlgGraph1 = SqlgGraph.open(configuration);
assertNotNull(this.sqlgGraph1);
assertEquals(this.sqlgGraph.getBuildVersion(), this.sqlgGraph1.getBuildVersion());
}
stopWatch.stop();
LOGGER.info("Startup time for test = " + stopWatch);
connection = this.sqlgGraph.tx().getConnection();
try (Statement statement = connection.createStatement()) {
statement.execute("CREATE EXTENSION IF NOT EXISTS postgres_fdw;");
String sql = String.format(
"CREATE SERVER \"%s\" FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host '%s', dbname '%s', port '%d');",
"sqlgraph_fwd_server",
"localhost",
"sqlgraphdb_fdw",
5432
);
statement.execute(sql);
this.sqlgGraph.tx().commit();
} catch (Exception e) {
//swallow
// LOGGER.error("Failed to create 'sqlgraph_fwd_server'", e);
} finally {
this.sqlgGraph.tx().rollback();
}
connection = sqlgGraph.tx().getConnection();
try (Statement statement = connection.createStatement()) {
String sql = String.format(
"CREATE USER MAPPING FOR %s SERVER \"%s\" OPTIONS (user '%s', password '%s');",
"postgres",
"sqlgraph_fwd_server",
"postgres",
"postgres"
);
statement.execute(sql);
this.sqlgGraph.tx().commit();
} catch (SQLException throwables) {
//swallow for mostly the server will already exist
} finally {
this.sqlgGraph.tx().rollback();
}
}
@After
public void after() {
try {
this.sqlgGraph.tx().onClose(Transaction.CLOSE_BEHAVIOR.ROLLBACK);
this.sqlgGraph.close();
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
try {
if (this.sqlgGraph1 != null) {
this.sqlgGraph1.tx().onClose(Transaction.CLOSE_BEHAVIOR.ROLLBACK);
this.sqlgGraph1.close();
}
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
try {
if (this.sqlgGraphFdw != null) {
this.sqlgGraphFdw.tx().onClose(Transaction.CLOSE_BEHAVIOR.ROLLBACK);
this.sqlgGraphFdw.close();
}
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
@Test
public void testImportForeignSchemaVertexLabels() throws SQLException {
this.sqlgGraph.getTopology().getPublicSchema().ensureVertexLabelExist(
"A",
new LinkedHashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}}
);
this.sqlgGraph.tx().commit();
Schema b = this.sqlgGraphFdw.getTopology().ensureSchemaExist("B");
@SuppressWarnings("UnusedAssignment")
VertexLabel bVertexLabel = b.ensureVertexLabelExist(
"B",
new LinkedHashMap<>() {{
put("b", PropertyDefinition.of(PropertyType.STRING));
}}
);
this.sqlgGraphFdw.tx().commit();
Connection connection = this.sqlgGraph.tx().getConnection();
try (Statement statement = connection.createStatement()) {
String sql = String.format(
"CREATE SCHEMA \"%s\";",
"B"
);
statement.execute(sql);
sql = String.format(
"IMPORT FOREIGN SCHEMA \"%s\" FROM SERVER \"%s\" INTO \"%s\";",
"B",
"sqlgraph_fwd_server",
"B"
);
statement.execute(sql);
}
this.sqlgGraph.tx().commit();
this.sqlgGraph.getTopology().importForeignSchemas(Set.of(this.sqlgGraphFdw.getTopology().getSchema("B").orElseThrow()));
Assert.assertTrue(this.sqlgGraph.getTopology().getSchema("B").isPresent());
//Check its readOnly
Schema foreignSchema = this.sqlgGraph.getTopology().getSchema("B").orElseThrow();
boolean failed = false;
try {
foreignSchema.ensureVertexLabelExist("D",
new LinkedHashMap<>() {{
put("d", PropertyDefinition.of(PropertyType.STRING));
}});
} catch (Exception e) {
Assert.assertTrue(e instanceof IllegalStateException);
Assert.assertEquals("'B' is a read only foreign schema!", e.getMessage());
failed = true;
}
Assert.assertTrue(failed);
failed = false;
try {
bVertexLabel = foreignSchema.getVertexLabel("B").orElseThrow();
Map<String, PropertyColumn> properties = bVertexLabel.getProperties();
Map<String, PropertyDefinition> propertyDefinitionMap = new HashMap<>();
for (String p : properties.keySet()) {
propertyDefinitionMap.put(p, properties.get(p).getPropertyDefinition());
}
propertyDefinitionMap.put("bb", PropertyDefinition.of(PropertyType.STRING));
bVertexLabel.ensurePropertiesExist(propertyDefinitionMap);
} catch (Exception e) {
Assert.assertTrue(e instanceof IllegalStateException);
Assert.assertEquals("'B' is a read only foreign VertexLabel!", e.getMessage());
failed = true;
}
Assert.assertTrue(failed);
this.sqlgGraphFdw.addVertex(T.label, "B.B", "b", "halo");
this.sqlgGraphFdw.tx().commit();
List<Vertex> vertices = this.sqlgGraph.traversal().V().hasLabel("B.B").toList();
Assert.assertEquals(1, vertices.size());
this.sqlgGraph.addVertex(T.label, "A", "a", "test");
this.sqlgGraph.tx().commit();
List<Vertex> aVertices = this.sqlgGraph.traversal().V().hasLabel("A").toList();
Assert.assertEquals(1, aVertices.size());
this.sqlgGraph.getTopology().getPublicSchema().ensureVertexLabelExist("C", new LinkedHashMap<>() {{
put("c", PropertyDefinition.of(PropertyType.STRING));
}});
this.sqlgGraph.tx().commit();
//Assert that one can not insert into a foreign table with sequence primary key.
failed = false;
try {
this.sqlgGraph.addVertex(T.label, "B.B", "b", "halo again");
} catch (IllegalStateException e) {
failed = true;
}
Assert.assertTrue(failed);
this.sqlgGraph.tx().rollback();
}
@Test
public void testImportForeignSchemaVertexAndEdgeLabels() throws SQLException {
Schema aSchema = this.sqlgGraphFdw.getTopology().ensureSchemaExist("A");
VertexLabel aVertexLabel = aSchema.ensureVertexLabelExist(
"A",
new LinkedHashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}}
);
VertexLabel bVertexLabel = aSchema.ensureVertexLabelExist(
"B",
new LinkedHashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}}
);
aVertexLabel.ensureEdgeLabelExist("ab", bVertexLabel, new HashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}});
this.sqlgGraphFdw.tx().commit();
Vertex a = this.sqlgGraphFdw.addVertex(T.label, "A.A", "a", "haloA");
Vertex b = this.sqlgGraphFdw.addVertex(T.label, "A.B", "a", "haloB");
a.addEdge("ab", b, "a", "halo ab");
this.sqlgGraphFdw.tx().commit();
List<Vertex> vertices = this.sqlgGraphFdw.traversal().V().hasLabel("A.A").out("ab").toList();
Assert.assertEquals(1, vertices.size());
this.sqlgGraphFdw.tx().rollback();
Connection connection = this.sqlgGraph.tx().getConnection();
try (Statement statement = connection.createStatement()) {
String sql = String.format(
"CREATE SCHEMA \"%s\";",
"A"
);
statement.execute(sql);
sql = String.format(
"IMPORT FOREIGN SCHEMA \"%s\" FROM SERVER \"%s\" INTO \"%s\";",
"A",
"sqlgraph_fwd_server",
"A"
);
statement.execute(sql);
}
this.sqlgGraph.tx().commit();
Schema a1 = this.sqlgGraphFdw.getTopology().getSchema("A").orElseThrow();
EdgeLabel ab = a1.getEdgeLabel("ab").orElseThrow();
this.sqlgGraph.getTopology().importForeignSchemas(Set.of(a1));
EdgeLabel ab_after = a1.getEdgeLabel("ab").orElseThrow();
VertexLabel aVertexLabel_after = a1.getVertexLabel("A").orElseThrow();
VertexLabel bVertexLabel_after = a1.getVertexLabel("B").orElseThrow();
Assert.assertSame(ab, ab_after);
Assert.assertSame(aVertexLabel, aVertexLabel_after);
Assert.assertSame(bVertexLabel, bVertexLabel_after);
Optional<Schema> schemaOptional = this.sqlgGraph.getTopology().getSchema("A");
Assert.assertTrue(schemaOptional.isPresent());
Assert.assertTrue(schemaOptional.get().isForeignSchema());
Schema aForeignSchema = schemaOptional.get();
Assert.assertTrue(aForeignSchema.getVertexLabel("A").isPresent());
Assert.assertTrue(aForeignSchema.getVertexLabel("A").get().isForeign());
VertexLabel aForeignVertexLabel = aForeignSchema.getVertexLabel("A").get();
Assert.assertTrue(aForeignSchema.getVertexLabel("B").isPresent());
Assert.assertTrue(aForeignSchema.getVertexLabel("B").get().isForeign());
Assert.assertTrue(aForeignSchema.getEdgeLabel("ab").isPresent());
Assert.assertTrue(aForeignSchema.getEdgeLabel("ab").get().isForeign());
vertices = this.sqlgGraph.traversal().V().hasLabel("A.A").toList();
Assert.assertEquals(1, vertices.size());
vertices = this.sqlgGraph.traversal().V().hasLabel("A.B").toList();
Assert.assertEquals(1, vertices.size());
vertices = this.sqlgGraph.traversal().V().hasLabel("A.A").out("ab").toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals("haloB", vertices.get(0).value("a"));
//This is important, postgres_fdw runs fetch queries which will dead lock on alter statements.
this.sqlgGraph.tx().rollback();
//Check its readOnly
boolean failed = false;
try {
aForeignSchema.ensureVertexLabelExist("C", new HashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}});
} catch (Exception e) {
Assert.assertTrue(e instanceof IllegalStateException);
Assert.assertEquals("'A' is a read only foreign schema!", e.getMessage());
failed = true;
}
Assert.assertTrue(failed);
//Add another VertexLabel
VertexLabel cVertexLabel = aSchema.ensureVertexLabelExist(
"C",
new LinkedHashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}}
);
aVertexLabel.ensureEdgeLabelExist("ac", cVertexLabel, new HashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}});
this.sqlgGraphFdw.tx().commit();
//Check its readOnly
failed = false;
try {
aForeignVertexLabel.ensureEdgeLabelExist("bc", cVertexLabel, new HashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}});
} catch (Exception e) {
Assert.assertTrue(e instanceof IllegalStateException);
Assert.assertEquals("'A' is a read only foreign schema!", e.getMessage());
failed = true;
}
Assert.assertTrue(failed);
//Check can not insert vertex via foreign label
failed = false;
try {
this.sqlgGraph.addVertex(T.label, "A.A", "a", "haloAgain");
} catch (IllegalStateException e) {
failed = true;
Assert.assertEquals("Foreign VertexLabel must have user defined identifiers to support addition.", e.getMessage());
}
Assert.assertTrue(failed);
this.sqlgGraph.tx().rollback();
//Check can not insert edge via foreign label
failed = false;
try {
vertices = this.sqlgGraph.traversal().V().hasLabel("A.A").toList();
Assert.assertEquals(1, vertices.size());
a = vertices.get(0);
vertices = this.sqlgGraph.traversal().V().hasLabel("A.B").toList();
Assert.assertEquals(1, vertices.size());
b = vertices.get(0);
a.addEdge("ab", b);
this.sqlgGraph.tx().commit();
} catch (IllegalStateException e) {
failed = true;
Assert.assertEquals("Foreign EdgeLabel must have user defined identifiers to support addition.", e.getMessage());
}
Assert.assertTrue(failed);
this.sqlgGraph.tx().rollback();
}
@Test
public void testVertexLabelWithSameNameInDifferentSchemas() {
Schema real = this.sqlgGraphFdw.getTopology().ensureSchemaExist("REAL");
VertexLabel realPerson = real.ensureVertexLabelExist("Person");
VertexLabel realSoftware = real.ensureVertexLabelExist("Software");
realPerson.ensureEdgeLabelExist("created", realSoftware);
Schema plan = this.sqlgGraphFdw.getTopology().ensureSchemaExist("PLAN");
VertexLabel planPerson = plan.ensureVertexLabelExist("Person");
VertexLabel planSoftware = plan.ensureVertexLabelExist("Software");
planPerson.ensureEdgeLabelExist("created", planSoftware);
this.sqlgGraphFdw.tx().commit();
this.sqlgGraph.getTopology().importForeignSchemas(Set.of(real, plan));
Map<String, VertexLabel> vertexLabelMap = real.getVertexLabels();
Assert.assertTrue(vertexLabelMap.containsKey("REAL.V_Person"));
Assert.assertTrue(vertexLabelMap.containsKey("REAL.V_Software"));
VertexLabel vertexLabel = vertexLabelMap.get("REAL.V_Person");
Map<String, EdgeLabel> edgeLabelMap = vertexLabel.getInEdgeLabels();
Assert.assertEquals(0, edgeLabelMap.size());
vertexLabel = vertexLabelMap.get("REAL.V_Software");
edgeLabelMap = vertexLabel.getInEdgeLabels();
Assert.assertEquals(1, edgeLabelMap.size());
Schema foreignReal = this.sqlgGraph.getTopology().getSchema("REAL").orElseThrow();
vertexLabelMap = foreignReal.getVertexLabels();
Assert.assertTrue(vertexLabelMap.containsKey("REAL.V_Person"));
Assert.assertTrue(vertexLabelMap.containsKey("REAL.V_Software"));
vertexLabel = vertexLabelMap.get("REAL.V_Person");
edgeLabelMap = vertexLabel.getInEdgeLabels();
Assert.assertEquals(0, edgeLabelMap.size());
vertexLabel = vertexLabelMap.get("REAL.V_Software");
edgeLabelMap = vertexLabel.getInEdgeLabels();
Assert.assertEquals(1, edgeLabelMap.size());
}
@Test
public void testReimportForeignSchema() {
Schema aSchema = this.sqlgGraphFdw.getTopology().ensureSchemaExist("A");
VertexLabel aVertexLabel = aSchema.ensureVertexLabelExist(
"A",
new LinkedHashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}}
);
VertexLabel bVertexLabel = aSchema.ensureVertexLabelExist(
"B",
new LinkedHashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}}
);
aVertexLabel.ensureEdgeLabelExist("ab", bVertexLabel, new HashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}});
this.sqlgGraphFdw.tx().commit();
this.sqlgGraph.getTopology().importForeignSchemas(Set.of(aSchema));
this.sqlgGraph.getTopology().clearForeignSchemas();
this.sqlgGraph.getTopology().importForeignSchemas(Set.of(aSchema));
Assert.assertTrue(this.sqlgGraph.getTopology().getSchema("A").isPresent());
Assert.assertTrue(this.sqlgGraph.getTopology().getSchema("A").orElseThrow().getVertexLabel("A").isPresent());
Assert.assertTrue(this.sqlgGraph.getTopology().getSchema("A").orElseThrow().getVertexLabel("B").isPresent());
}
@Test
public void testImportForeignSchemaEdgeLabelAcrossSchemaInVertexLabelFailure1() throws SQLException {
Schema aSchema = this.sqlgGraphFdw.getTopology().ensureSchemaExist("A");
Schema bSchema = this.sqlgGraphFdw.getTopology().ensureSchemaExist("B");
VertexLabel aVertexLabel = aSchema.ensureVertexLabelExist(
"A",
new LinkedHashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}}
);
VertexLabel bVertexLabel = bSchema.ensureVertexLabelExist(
"B",
new LinkedHashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}}
);
aVertexLabel.ensureEdgeLabelExist("ab", bVertexLabel, new HashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}});
this.sqlgGraphFdw.tx().commit();
Vertex a = this.sqlgGraphFdw.addVertex(T.label, "A.A", "a", "haloA");
Vertex b = this.sqlgGraphFdw.addVertex(T.label, "B.B", "a", "haloB");
a.addEdge("ab", b, "a", "halo ab");
this.sqlgGraphFdw.tx().commit();
List<Vertex> vertices = this.sqlgGraphFdw.traversal().V().hasLabel("A.A").out("ab").toList();
Assert.assertEquals(1, vertices.size());
this.sqlgGraphFdw.tx().rollback();
Connection connection = this.sqlgGraph.tx().getConnection();
try (Statement statement = connection.createStatement()) {
String sql = String.format(
"CREATE SCHEMA \"%s\";",
"A"
);
statement.execute(sql);
sql = String.format(
"IMPORT FOREIGN SCHEMA \"%s\" FROM SERVER \"%s\" INTO \"%s\";",
"A",
"sqlgraph_fwd_server",
"A"
);
statement.execute(sql);
}
this.sqlgGraph.tx().commit();
boolean failed = false;
try {
this.sqlgGraph.getTopology().importForeignSchemas(Set.of(this.sqlgGraphFdw.getTopology().getSchema("A").orElseThrow()));
} catch (Exception e) {
failed = true;
Assert.assertTrue(e instanceof IllegalStateException);
Assert.assertEquals("EdgeLabel 'A.E_ab' has a inVertexLabel 'B' that is not present in a foreign schema", e.getMessage());
}
Assert.assertTrue(failed);
}
@Test
public void testImportForeignSchemaEdgeLabelAcrossSchemaOutVertexLabelFailure1() throws SQLException {
Schema aSchema = this.sqlgGraphFdw.getTopology().ensureSchemaExist("A");
Schema bSchema = this.sqlgGraphFdw.getTopology().ensureSchemaExist("B");
VertexLabel aVertexLabel = aSchema.ensureVertexLabelExist(
"A",
new LinkedHashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}}
);
VertexLabel bVertexLabel = bSchema.ensureVertexLabelExist(
"B",
new LinkedHashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}}
);
aVertexLabel.ensureEdgeLabelExist("ab", bVertexLabel, new HashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}});
this.sqlgGraphFdw.tx().commit();
Vertex a = this.sqlgGraphFdw.addVertex(T.label, "A.A", "a", "haloA");
Vertex b = this.sqlgGraphFdw.addVertex(T.label, "B.B", "a", "haloB");
a.addEdge("ab", b, "a", "halo ab");
this.sqlgGraphFdw.tx().commit();
List<Vertex> vertices = this.sqlgGraphFdw.traversal().V().hasLabel("A.A").out("ab").toList();
Assert.assertEquals(1, vertices.size());
this.sqlgGraphFdw.tx().rollback();
Connection connection = this.sqlgGraph.tx().getConnection();
try (Statement statement = connection.createStatement()) {
String sql = String.format(
"CREATE SCHEMA \"%s\";",
"B"
);
statement.execute(sql);
sql = String.format(
"IMPORT FOREIGN SCHEMA \"%s\" FROM SERVER \"%s\" INTO \"%s\";",
"B",
"sqlgraph_fwd_server",
"B"
);
statement.execute(sql);
}
this.sqlgGraph.tx().commit();
boolean failed = false;
try {
this.sqlgGraph.getTopology().importForeignSchemas(Set.of(this.sqlgGraphFdw.getTopology().getSchema("B").orElseThrow()));
} catch (Exception e) {
failed = true;
Assert.assertTrue(e instanceof IllegalStateException);
Assert.assertEquals("VertexLabel 'B.V_B' has an inEdgeLabel 'ab' that is not present in a foreign schema", e.getMessage());
}
Assert.assertTrue(failed);
}
@Test
public void testImportForeignSchemaEdgeLabelAcrossSchemaOutVertexLabelSuccess() throws SQLException {
Schema aSchema = this.sqlgGraphFdw.getTopology().ensureSchemaExist("A");
Schema bSchema = this.sqlgGraphFdw.getTopology().ensureSchemaExist("B");
VertexLabel aVertexLabel = aSchema.ensureVertexLabelExist(
"A",
new LinkedHashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}}
);
VertexLabel bVertexLabel = bSchema.ensureVertexLabelExist(
"B",
new LinkedHashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}}
);
aVertexLabel.ensureEdgeLabelExist("ab", bVertexLabel, new HashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}});
this.sqlgGraphFdw.tx().commit();
Vertex a = this.sqlgGraphFdw.addVertex(T.label, "A.A", "a", "haloA");
Vertex b = this.sqlgGraphFdw.addVertex(T.label, "B.B", "a", "haloB");
a.addEdge("ab", b, "a", "halo ab");
this.sqlgGraphFdw.tx().commit();
List<Vertex> vertices = this.sqlgGraphFdw.traversal().V().hasLabel("A.A").out("ab").toList();
Assert.assertEquals(1, vertices.size());
vertices = this.sqlgGraphFdw.traversal().V().hasLabel("B.B").in("ab").toList();
Assert.assertEquals(1, vertices.size());
vertices = this.sqlgGraphFdw.traversal().E().hasLabel("ab").inV().toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals("B.B", vertices.get(0).label());
this.sqlgGraphFdw.tx().rollback();
Connection connection = this.sqlgGraph.tx().getConnection();
try (Statement statement = connection.createStatement()) {
String sql = String.format(
"CREATE SCHEMA \"%s\";",
"A"
);
statement.execute(sql);
sql = String.format(
"CREATE SCHEMA \"%s\";",
"B"
);
statement.execute(sql);
sql = String.format(
"IMPORT FOREIGN SCHEMA \"%s\" FROM SERVER \"%s\" INTO \"%s\";",
"A",
"sqlgraph_fwd_server",
"A"
);
statement.execute(sql);
sql = String.format(
"IMPORT FOREIGN SCHEMA \"%s\" FROM SERVER \"%s\" INTO \"%s\";",
"B",
"sqlgraph_fwd_server",
"B"
);
statement.execute(sql);
}
this.sqlgGraph.tx().commit();
this.sqlgGraph.getTopology().importForeignSchemas(Set.of(
this.sqlgGraphFdw.getTopology().getSchema("A").orElseThrow(),
this.sqlgGraphFdw.getTopology().getSchema("B").orElseThrow()
));
vertices = this.sqlgGraph.traversal().V().hasLabel("A.A").out().toList();
Assert.assertEquals(1, vertices.size());
vertices = this.sqlgGraph.traversal().V().hasLabel("A.A").out("ab").toList();
Assert.assertEquals(1, vertices.size());
vertices = this.sqlgGraph.traversal().V().hasLabel("B.B").in("ab").toList();
Assert.assertEquals(1, vertices.size());
List<Edge> edges = this.sqlgGraph.traversal().E().hasLabel("ab").toList();
Assert.assertEquals(1, edges.size());
vertices = this.sqlgGraph.traversal().E().hasLabel("ab").inV().toList();
Assert.assertEquals(1, vertices.size());
Assert.assertEquals("B.B", vertices.get(0).label());
edges = this.sqlgGraph.traversal().V().hasLabel("A.A").outE().toList();
Assert.assertEquals(1, edges.size());
edges = this.sqlgGraph.traversal().V().hasLabel("B.B").outE().toList();
Assert.assertEquals(0, edges.size());
edges = this.sqlgGraph.traversal().V().hasLabel("B.B").inE().toList();
Assert.assertEquals(1, edges.size());
this.sqlgGraph.getTopology().clearForeignSchemas();
Assert.assertTrue(this.sqlgGraph.getTopology().getSchema("A").isEmpty());
Assert.assertTrue(this.sqlgGraph.getTopology().getSchema("B").isEmpty());
}
@Test
public void testImportForeignSchemaVertexAndEdgeLabelInPublic() throws SQLException {
VertexLabel aVertexLabel = this.sqlgGraphFdw.getTopology().getPublicSchema().ensureVertexLabelExist(
"A",
new LinkedHashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}}
);
VertexLabel bVertexLabel = this.sqlgGraphFdw.getTopology().getPublicSchema().ensureVertexLabelExist(
"B",
new LinkedHashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}}
);
@SuppressWarnings("unused")
EdgeLabel edgeLabel = aVertexLabel.ensureEdgeLabelExist("ab", bVertexLabel, new HashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}});
Vertex a = this.sqlgGraphFdw.addVertex(T.label, "A", "a", "halo A");
Vertex b = this.sqlgGraphFdw.addVertex(T.label, "B", "a", "halo B");
a.addEdge("ab", b, "a", "halo ab edge");
this.sqlgGraphFdw.tx().commit();
Connection connection = this.sqlgGraph.tx().getConnection();
try (Statement statement = connection.createStatement()) {
String sql = String.format(
"IMPORT FOREIGN SCHEMA \"%s\" LIMIT TO (%s) FROM SERVER \"%s\" INTO \"%s\";",
this.sqlgGraph.getSqlDialect().getPublicSchema(),
"\"V_A\",\"V_B\",\"E_ab\"",
"sqlgraph_fwd_server",
this.sqlgGraph.getSqlDialect().getPublicSchema()
);
statement.execute(sql);
}
this.sqlgGraph.tx().commit();
VertexLabel foreignAVertexLabel = this.sqlgGraphFdw.getTopology().getPublicSchema().getVertexLabel("A").orElseThrow();
VertexLabel foreignBVertexLabel = this.sqlgGraphFdw.getTopology().getPublicSchema().getVertexLabel("B").orElseThrow();
EdgeLabel foreignABEdgeLabel = this.sqlgGraphFdw.getTopology().getPublicSchema().getEdgeLabel("ab").orElseThrow();
this.sqlgGraph.getTopology().importForeignVertexEdgeLabels(
this.sqlgGraph.getTopology().getPublicSchema(),
Set.of(foreignAVertexLabel, foreignBVertexLabel),
Set.of(foreignABEdgeLabel)
);
Assert.assertTrue(this.sqlgGraph.getTopology().getPublicSchema().getVertexLabel("A").isPresent());
Assert.assertTrue(this.sqlgGraph.getTopology().getPublicSchema().getVertexLabel("B").isPresent());
Assert.assertTrue(this.sqlgGraph.getTopology().getPublicSchema().getEdgeLabel("ab").isPresent());
List<Vertex> aVertices = this.sqlgGraph.traversal().V().hasLabel("A").toList();
Assert.assertEquals(1, aVertices.size());
List<Vertex> bVertices = this.sqlgGraph.traversal().V().hasLabel("B").toList();
Assert.assertEquals(1, bVertices.size());
List<Edge> abEdges = this.sqlgGraph.traversal().E().hasLabel("ab").toList();
Assert.assertEquals(1, abEdges.size());
bVertices = this.sqlgGraph.traversal().V().hasLabel("A").out().toList();
Assert.assertEquals(1, bVertices.size());
this.sqlgGraph.getTopology().clearForeignSchemas();
Assert.assertFalse(this.sqlgGraph.getTopology().getPublicSchema().getVertexLabel("A").isPresent());
Assert.assertFalse(this.sqlgGraph.getTopology().getPublicSchema().getVertexLabel("B").isPresent());
Assert.assertFalse(this.sqlgGraph.getTopology().getPublicSchema().getEdgeLabel("ab").isPresent());
}
@Test
public void testImportForeignSchemaVertexAndEdgeLabelInPublicFailure() throws SQLException {
VertexLabel aVertexLabel = this.sqlgGraphFdw.getTopology().getPublicSchema().ensureVertexLabelExist(
"A",
new LinkedHashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}}
);
VertexLabel bVertexLabel = this.sqlgGraphFdw.getTopology().getPublicSchema().ensureVertexLabelExist(
"B",
new LinkedHashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}}
);
@SuppressWarnings("unused")
EdgeLabel edgeLabel = aVertexLabel.ensureEdgeLabelExist("ab", bVertexLabel, new HashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}});
@SuppressWarnings("unused")
EdgeLabel baEdgeLabel = bVertexLabel.ensureEdgeLabelExist("ba", aVertexLabel, new HashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}});
Vertex a = this.sqlgGraphFdw.addVertex(T.label, "A", "a", "halo A");
Vertex b = this.sqlgGraphFdw.addVertex(T.label, "B", "a", "halo B");
a.addEdge("ab", b, "a", "halo ab edge");
b.addEdge("ba", a, "a", "halo ba edge");
this.sqlgGraphFdw.tx().commit();
Connection connection = this.sqlgGraph.tx().getConnection();
try (Statement statement = connection.createStatement()) {
String sql = String.format(
"IMPORT FOREIGN SCHEMA \"%s\" LIMIT TO (%s) FROM SERVER \"%s\" INTO \"%s\";",
this.sqlgGraph.getSqlDialect().getPublicSchema(),
"\"V_A\",\"V_B\",\"E_ab\",\"E_ba\"",
"sqlgraph_fwd_server",
this.sqlgGraph.getSqlDialect().getPublicSchema()
);
statement.execute(sql);
}
this.sqlgGraph.tx().commit();
VertexLabel foreignAVertexLabel = this.sqlgGraphFdw.getTopology().getPublicSchema().getVertexLabel("A").orElseThrow();
VertexLabel foreignBVertexLabel = this.sqlgGraphFdw.getTopology().getPublicSchema().getVertexLabel("B").orElseThrow();
EdgeLabel foreignABEdgeLabel = this.sqlgGraphFdw.getTopology().getPublicSchema().getEdgeLabel("ab").orElseThrow();
EdgeLabel foreignBAEdgeLabel = this.sqlgGraphFdw.getTopology().getPublicSchema().getEdgeLabel("ba").orElseThrow();
boolean failure = false;
try {
this.sqlgGraph.getTopology().importForeignVertexEdgeLabels(
this.sqlgGraph.getTopology().getPublicSchema(),
Set.of(foreignAVertexLabel, foreignBVertexLabel),
Set.of(foreignABEdgeLabel)
);
} catch (Exception e) {
failure = true;
Assert.assertTrue(e instanceof IllegalStateException);
Assert.assertEquals("'public.E_public.ba' is not present in the foreign EdgeLabels", e.getMessage());
}
Assert.assertTrue(failure);
this.sqlgGraph.getTopology().importForeignVertexEdgeLabels(
this.sqlgGraph.getTopology().getPublicSchema(),
Set.of(foreignAVertexLabel, foreignBVertexLabel),
Set.of(foreignABEdgeLabel, foreignBAEdgeLabel)
);
Optional<VertexLabel> vertexLabelOptional = this.sqlgGraph.getTopology().getPublicSchema().getVertexLabel("A");
Assert.assertTrue(vertexLabelOptional.isPresent());
Assert.assertTrue(vertexLabelOptional.get().isForeign());
vertexLabelOptional = this.sqlgGraph.getTopology().getPublicSchema().getVertexLabel("B");
Assert.assertTrue(vertexLabelOptional.isPresent());
Assert.assertTrue(vertexLabelOptional.get().isForeign());
Optional<EdgeLabel> edgeLabelOptional = this.sqlgGraph.getTopology().getPublicSchema().getEdgeLabel("ab");
Assert.assertTrue(edgeLabelOptional.isPresent());
Assert.assertTrue(edgeLabelOptional.get().isForeign());
edgeLabelOptional = this.sqlgGraph.getTopology().getPublicSchema().getEdgeLabel("ba");
Assert.assertTrue(edgeLabelOptional.isPresent());
Assert.assertTrue(edgeLabelOptional.get().isForeign());
List<Vertex> aVertices = this.sqlgGraph.traversal().V().hasLabel("A").toList();
Assert.assertEquals(1, aVertices.size());
List<Vertex> bVertices = this.sqlgGraph.traversal().V().hasLabel("B").toList();
Assert.assertEquals(1, bVertices.size());
List<Edge> abEdges = this.sqlgGraph.traversal().E().hasLabel("ab").toList();
Assert.assertEquals(1, abEdges.size());
List<Edge> baEdges = this.sqlgGraph.traversal().E().hasLabel("ba").toList();
Assert.assertEquals(1, baEdges.size());
bVertices = this.sqlgGraph.traversal().V().hasLabel("A").out().toList();
Assert.assertEquals(1, bVertices.size());
bVertices = this.sqlgGraph.traversal().V().hasLabel("A").in().toList();
Assert.assertEquals(1, bVertices.size());
}
@Test
public void importTinkerPopClassic() throws SQLException {
loadModern(this.sqlgGraphFdw);
this.sqlgGraphFdw.tx().commit();
VertexLabel person = this.sqlgGraphFdw.getTopology().getPublicSchema().getVertexLabel("person").orElseThrow();
VertexLabel software = this.sqlgGraphFdw.getTopology().getPublicSchema().getVertexLabel("software").orElseThrow();
EdgeLabel created = this.sqlgGraphFdw.getTopology().getPublicSchema().getEdgeLabel("created").orElseThrow();
EdgeLabel knows = this.sqlgGraphFdw.getTopology().getPublicSchema().getEdgeLabel("knows").orElseThrow();
Connection connection = this.sqlgGraph.tx().getConnection();
try (Statement statement = connection.createStatement()) {
String sql = String.format(
"IMPORT FOREIGN SCHEMA \"%s\" LIMIT TO (%s) FROM SERVER \"%s\" INTO \"%s\";",
this.sqlgGraph.getSqlDialect().getPublicSchema(),
"\"V_person\",\"V_software\",\"E_created\",\"E_knows\"",
"sqlgraph_fwd_server",
this.sqlgGraph.getSqlDialect().getPublicSchema()
);
statement.execute(sql);
}
this.sqlgGraph.tx().commit();
this.sqlgGraph.getTopology().importForeignVertexEdgeLabels(
this.sqlgGraph.getTopology().getPublicSchema(),
Set.of(person, software),
Set.of(created, knows)
);
final Traversal<Vertex, Map<String, Map<String, Map<String, Object>>>> traversal = this.sqlgGraph.traversal()
.V().hasLabel("person")
.filter(__.outE("created")).aggregate("p").as("p1").values("name").as("p1n")
.select("p").unfold().where(P.neq("p1")).as("p2").values("name").as("p2n").select("p2")
.out("created").choose(__.in("created").where(P.eq("p1")), __.values("name"), __.constant(Collections.emptyList()))
.<String, Map<String, Map<String, Object>>>group().by(__.select("p1n")).
by(__.group().by(__.select("p2n")).
by(__.unfold().fold().project("numCoCreated", "coCreated").by(__.count(Scope.local)).by()));
this.printTraversalForm(traversal);
Assert.assertTrue(traversal.hasNext());
checkCoworkerSummary(traversal.next());
Assert.assertFalse(traversal.hasNext());
}
private static void checkCoworkerSummary(final Map<String, Map<String, Map<String, Object>>> summary) {
Assert.assertNotNull(summary);
Assert.assertEquals(3, summary.size());
Assert.assertTrue(summary.containsKey("marko"));
Assert.assertTrue(summary.containsKey("josh"));
Assert.assertTrue(summary.containsKey("peter"));
for (final Map.Entry<String, Map<String, Map<String, Object>>> entry : summary.entrySet()) {
assertEquals(2, entry.getValue().size());
switch (entry.getKey()) {
case "marko":
Assert.assertTrue(entry.getValue().containsKey("josh") && entry.getValue().containsKey("peter"));
break;
case "josh":
Assert.assertTrue(entry.getValue().containsKey("peter") && entry.getValue().containsKey("marko"));
break;
case "peter":
Assert.assertTrue(entry.getValue().containsKey("marko") && entry.getValue().containsKey("josh"));
break;
}
for (final Map<String, Object> m : entry.getValue().values()) {
Assert.assertTrue(m.containsKey("numCoCreated"));
Assert.assertTrue(m.containsKey("coCreated"));
Assert.assertTrue(m.get("numCoCreated") instanceof Number);
Assert.assertTrue(m.get("coCreated") instanceof Collection);
Assert.assertEquals(1, ((Number) m.get("numCoCreated")).intValue());
Assert.assertEquals(1, ((Collection) m.get("coCreated")).size());
Assert.assertEquals("lop", ((Collection) m.get("coCreated")).iterator().next());
}
}
}
@Test
public void importTinkerPopGratefulDead() throws SQLException {
loadGratefulDead(this.sqlgGraphFdw);
this.sqlgGraphFdw.tx().commit();
VertexLabel song = this.sqlgGraphFdw.getTopology().getPublicSchema().getVertexLabel("song").orElseThrow();
VertexLabel artist = this.sqlgGraphFdw.getTopology().getPublicSchema().getVertexLabel("artist").orElseThrow();
EdgeLabel followedBy = this.sqlgGraphFdw.getTopology().getPublicSchema().getEdgeLabel("followedBy").orElseThrow();
EdgeLabel writtenBy = this.sqlgGraphFdw.getTopology().getPublicSchema().getEdgeLabel("writtenBy").orElseThrow();
EdgeLabel sungBy = this.sqlgGraphFdw.getTopology().getPublicSchema().getEdgeLabel("sungBy").orElseThrow();
Connection connection = this.sqlgGraph.tx().getConnection();
try (Statement statement = connection.createStatement()) {
String sql = String.format(
"IMPORT FOREIGN SCHEMA \"%s\" LIMIT TO (%s) FROM SERVER \"%s\" INTO \"%s\";",
this.sqlgGraph.getSqlDialect().getPublicSchema(),
"\"V_song\",\"V_artist\",\"E_followedBy\",\"E_writtenBy\", \"E_sungBy\"",
"sqlgraph_fwd_server",
this.sqlgGraph.getSqlDialect().getPublicSchema()
);
statement.execute(sql);
}
this.sqlgGraph.tx().commit();
this.sqlgGraph.getTopology().importForeignVertexEdgeLabels(
this.sqlgGraph.getTopology().getPublicSchema(),
Set.of(song, artist),
Set.of(followedBy, writtenBy, sungBy)
);
final Traversal<Vertex, Map<String, List<String>>> traversal = getPlaylistPaths();
printTraversalForm(traversal);
Assert.assertTrue(traversal.hasNext());
Map<String, List<String>> map = traversal.next();
Assert.assertTrue(map.get("artists").contains("Bob_Dylan"));
boolean hasJohnnyCash = false;
while (traversal.hasNext()) {
map = traversal.next();
if (map.get("artists").contains("Johnny_Cash"))
hasJohnnyCash = true;
}
Assert.assertTrue(hasJohnnyCash);
Assert.assertTrue(map.get("artists").contains("Grateful_Dead"));
}
@SuppressWarnings("unchecked")
private Traversal<Vertex, Map<String, List<String>>> getPlaylistPaths() {
return this.sqlgGraph.traversal().V().has("name", "Bob_Dylan").in("sungBy").as("a").
repeat(__.out().order().by(Order.shuffle).simplePath().from("a")).
until(__.out("writtenBy").has("name", "Johnny_Cash")).limit(1).as("b").
repeat(__.out().order().by(Order.shuffle).as("c").simplePath().from("b").to("c")).
until(__.out("sungBy").has("name", "Grateful_Dead")).limit(1).
path().from("a").unfold().
<List<String>>project("song", "artists").
by("name").
by(__.coalesce(__.out("sungBy", "writtenBy").dedup().values("name"), __.constant("Unknown")).fold());
}
@Test
public void testQueryViaFDW_WhileInsertingDirectly() throws SQLException, InterruptedException {
this.sqlgGraphFdw.getTopology().getPublicSchema().ensureVertexLabelExist(
"A",
new LinkedHashMap<>() {{
put("a", PropertyDefinition.of(PropertyType.STRING));
}}
);
this.sqlgGraphFdw.tx().commit();
Connection connection = this.sqlgGraph.tx().getConnection();
try (Statement statement = connection.createStatement()) {
String sql = String.format(
"IMPORT FOREIGN SCHEMA \"%s\" LIMIT TO (%s) FROM SERVER \"%s\" INTO \"%s\";",
this.sqlgGraph.getSqlDialect().getPublicSchema(),
"\"V_A\"",
"sqlgraph_fwd_server",
this.sqlgGraph.getSqlDialect().getPublicSchema()
);
statement.execute(sql);
}
this.sqlgGraph.tx().commit();
ExecutorService executorService1 = Executors.newFixedThreadPool(1);
executorService1.submit(() -> {
for (int i = 0; i < 10_000; i++) {
this.sqlgGraphFdw.addVertex(T.label, "A", "a", "halo A");
}
this.sqlgGraphFdw.tx().commit();
LOGGER.info("Completed executorService1");
});
ExecutorService executorService2 = Executors.newFixedThreadPool(1);
executorService2.submit(() -> {
for (int i = 0; i < 10_000; i++) {
List<Vertex> vertices = this.sqlgGraph.traversal().V().hasLabel("A").toList();
Assert.assertEquals(0, vertices.size());
}
this.sqlgGraphFdw.tx().rollback();
LOGGER.info("Completed executorService2");
});
executorService1.shutdown();
if (!executorService1.awaitTermination(1, TimeUnit.MINUTES)) {
Assert.fail("ExecutorService did not shutdown in 1 minute");
}
executorService2.shutdown();
if (!executorService2.awaitTermination(1, TimeUnit.MINUTES)) {
Assert.fail("ExecutorService did not shutdown in 1 minute");
}
LOGGER.debug("Done");
}
@Test
public void testInsertViaForeignSchema() throws SQLException {
this.sqlgGraph.getTopology().getPublicSchema().ensureVertexLabelExist(
"A",
new LinkedHashMap<>() {{
put("uuid", PropertyDefinition.of(PropertyType.UUID));
put("a", PropertyDefinition.of(PropertyType.STRING));
}},
ListOrderedSet.listOrderedSet(Set.of("uuid"))
);
this.sqlgGraph.tx().commit();
Schema b = this.sqlgGraphFdw.getTopology().ensureSchemaExist("B");
@SuppressWarnings("UnusedAssignment")
VertexLabel bVertexLabel = b.ensureVertexLabelExist(
"B",
new LinkedHashMap<>() {{
put("uuid", PropertyDefinition.of(PropertyType.UUID));
put("b", PropertyDefinition.of(PropertyType.STRING));
}},
ListOrderedSet.listOrderedSet(Set.of("uuid"))
);
this.sqlgGraphFdw.tx().commit();
Connection connection = this.sqlgGraph.tx().getConnection();
try (Statement statement = connection.createStatement()) {
String sql = String.format(
"CREATE SCHEMA \"%s\";",
"B"
);
statement.execute(sql);
sql = String.format(
"IMPORT FOREIGN SCHEMA \"%s\" FROM SERVER \"%s\" INTO \"%s\";",
"B",
"sqlgraph_fwd_server",
"B"
);
statement.execute(sql);
}
this.sqlgGraph.tx().commit();
this.sqlgGraph.getTopology().importForeignSchemas(Set.of(this.sqlgGraphFdw.getTopology().getSchema("B").orElseThrow()));
Assert.assertTrue(this.sqlgGraph.getTopology().getSchema("B").isPresent());
//Check its readOnly
Schema foreignSchema = this.sqlgGraph.getTopology().getSchema("B").orElseThrow();
boolean failed = false;
try {
foreignSchema.ensureVertexLabelExist("D",
new LinkedHashMap<>() {{
put("d", PropertyDefinition.of(PropertyType.STRING));
}});
} catch (Exception e) {
Assert.assertTrue(e instanceof IllegalStateException);
Assert.assertEquals("'B' is a read only foreign schema!", e.getMessage());
failed = true;
}
Assert.assertTrue(failed);
failed = false;
try {
bVertexLabel = foreignSchema.getVertexLabel("B").orElseThrow();
Map<String, PropertyColumn> properties = bVertexLabel.getProperties();
Map<String, PropertyDefinition> propertyDefinitionMap = new HashMap<>();
for (String p : properties.keySet()) {
propertyDefinitionMap.put(p, properties.get(p).getPropertyDefinition());
}
propertyDefinitionMap.put("bb", PropertyDefinition.of(PropertyType.STRING));
bVertexLabel.ensurePropertiesExist(propertyDefinitionMap);
} catch (Exception e) {
Assert.assertTrue(e instanceof IllegalStateException);
Assert.assertEquals("'B' is a read only foreign VertexLabel!", e.getMessage());
failed = true;
}
Assert.assertTrue(failed);
this.sqlgGraphFdw.addVertex(T.label, "B.B", "uuid", UUID.randomUUID(), "b", "halo");
this.sqlgGraphFdw.tx().commit();
List<Vertex> vertices = this.sqlgGraph.traversal().V().hasLabel("B.B").toList();
Assert.assertEquals(1, vertices.size());
this.sqlgGraph.addVertex(T.label, "A", "uuid", UUID.randomUUID(), "a", "test");
this.sqlgGraph.tx().commit();
List<Vertex> aVertices = this.sqlgGraph.traversal().V().hasLabel("A").toList();
Assert.assertEquals(1, aVertices.size());
this.sqlgGraph.getTopology().getPublicSchema().ensureVertexLabelExist("C", new LinkedHashMap<>() {{
put("c", PropertyDefinition.of(PropertyType.STRING));
}});
this.sqlgGraph.tx().commit();
//Assert that one can not insert into a foreign table with sequence primary key.
failed = false;
try {
this.sqlgGraph.addVertex(T.label, "B.B", "uuid", UUID.randomUUID(), "b", "halo again");
} catch (IllegalStateException e) {
failed = true;
}
Assert.assertFalse(failed);
this.sqlgGraph.tx().commit();
Assert.assertEquals(2, this.sqlgGraphFdw.traversal().V().hasLabel("B.B").count().next(), 0L);
Assert.assertEquals(2, this.sqlgGraph.traversal().V().hasLabel("B.B").count().next(), 0L);
this.sqlgGraph.tx().rollback();
this.sqlgGraphFdw.tx().rollback();
}
@Test
public void testInsertEdgesViaForeignSchema() throws SQLException {
Schema a = this.sqlgGraphFdw.getTopology().ensureSchemaExist("A");
VertexLabel aVertexLabel = a.ensureVertexLabelExist(
"A",
new LinkedHashMap<>() {{
put("uuid", PropertyDefinition.of(PropertyType.UUID));
put("name", PropertyDefinition.of(PropertyType.STRING));
}},
ListOrderedSet.listOrderedSet(Set.of("uuid"))
);
VertexLabel bVertexLabel = a.ensureVertexLabelExist(
"B",
new LinkedHashMap<>() {{
put("uuid", PropertyDefinition.of(PropertyType.UUID));
put("name", PropertyDefinition.of(PropertyType.STRING));
}},
ListOrderedSet.listOrderedSet(Set.of("uuid"))
);
aVertexLabel.ensureEdgeLabelExist("ab", bVertexLabel,
new HashMap<>() {{
put("uuid", PropertyDefinition.of(PropertyType.UUID));
}},
ListOrderedSet.listOrderedSet(Set.of("uuid"))
);
this.sqlgGraphFdw.tx().commit();
Connection connection = this.sqlgGraph.tx().getConnection();
try (Statement statement = connection.createStatement()) {
String sql = String.format(
"CREATE SCHEMA \"%s\";",
"A"
);
statement.execute(sql);
sql = String.format(
"IMPORT FOREIGN SCHEMA \"%s\" FROM SERVER \"%s\" INTO \"%s\" OPTIONS (import_default 'true');",
"A",
"sqlgraph_fwd_server",
"A"
);
statement.execute(sql);
}
this.sqlgGraph.tx().commit();
this.sqlgGraph.getTopology().importForeignSchemas(Set.of(this.sqlgGraphFdw.getTopology().getSchema("A").orElseThrow()));
Assert.assertTrue(this.sqlgGraph.getTopology().getSchema("A").isPresent());
Vertex a1 = this.sqlgGraph.addVertex(T.label, "A.A", "uuid", UUID.randomUUID(), "name", "a1");
Vertex a2 = this.sqlgGraph.addVertex(T.label, "A.A", "uuid", UUID.randomUUID(), "name", "a2");
Vertex b1 = this.sqlgGraph.addVertex(T.label, "A.B", "uuid", UUID.randomUUID(), "name", "b1");
Vertex b2 = this.sqlgGraph.addVertex(T.label, "A.B", "uuid", UUID.randomUUID(), "name", "b2");
a1.addEdge("ab", b1, "uuid", UUID.randomUUID());
a1.addEdge("ab", b2, "uuid", UUID.randomUUID());
a2.addEdge("ab", b1, "uuid", UUID.randomUUID());
a2.addEdge("ab", b2, "uuid", UUID.randomUUID());
this.sqlgGraph.tx().commit();
Assert.assertEquals(2, this.sqlgGraphFdw.traversal().V().hasLabel("A.A").count().next(), 0L);
Assert.assertEquals(2, this.sqlgGraph.traversal().V().hasLabel("A.A").count().next(), 0L);
Assert.assertEquals(2, this.sqlgGraphFdw.traversal().V().hasLabel("A.B").count().next(), 0L);
Assert.assertEquals(2, this.sqlgGraph.traversal().V().hasLabel("A.B").count().next(), 0L);
Assert.assertEquals(4, this.sqlgGraphFdw.traversal().E().hasLabel("A.ab").count().next(), 0L);
Assert.assertEquals(4, this.sqlgGraph.traversal().E().hasLabel("A.ab").count().next(), 0L);
Assert.assertEquals(2, this.sqlgGraphFdw.traversal().V(a1.id()).out("ab").count().next(), 0L);
Assert.assertEquals(2, this.sqlgGraphFdw.traversal().V(a2.id()).out("ab").count().next(), 0L);
Assert.assertEquals(2, this.sqlgGraphFdw.traversal().V(b1.id()).in("ab").count().next(), 0L);
Assert.assertEquals(2, this.sqlgGraphFdw.traversal().V(b2.id()).in("ab").count().next(), 0L);
this.sqlgGraph.tx().rollback();
this.sqlgGraphFdw.tx().rollback();
}
}