Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 22 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# In-memory Object Graph Stores
<img src="images/estore_logo.png" width="700" />
<img src="images/estore_logo.png" width="400" />

Implementation of an in-memory object graph store, dubbed ϵStore. Our
key innovation is a storage model -- epsilon store -- that equates an
Expand All @@ -23,24 +23,41 @@ programs.

Estore db = new Estore("exampleDb", new EstoreOptions().useUnsafe(false));
db.captureAll(alice);

// MATCH finds Person objects; RETURN puts them in column p
Table result = db.query("MATCH (p:`org.estore.example.Person`) RETURN p");

result.print();
Person p = (Person) result.get("p").get(0);
System.out.println(p.name + ", " + p.age);
System.out.println(p.friend.name);
```

`alice` is an ordinary Java `Person` object (name `"Alice"`, age 28). Its
`friend` field points to Bob, and Bob's `friend` field points to Charlie, so
the in-memory graph is Alice → Bob → Charlie. `captureAll(alice)` walks that
graph from Alice and stores every reachable object; the query then returns
the captured `Person` nodes.
graph from Alice and stores every reachable object. The query finds those
`Person` objects (`MATCH`) and returns them as a table column named `p`
(`RETURN`). Cells in that table are the same heap objects, so they can be
printed, cast to `Person`, and used like any other Java object — including
following `friend` in ordinary Java.

2. Querying object relationships.

```java
Table friends =
db.query("MATCH (a:`org.estore.example.Person`)-[:friend]->(b:`org.estore.example.Person`) RETURN a, b");

for (int i = 0; i < friends.getSize(); i++) {
Person a = (Person) friends.get("a").get(i);
Person b = (Person) friends.get("b").get(i);
System.out.println(a.name + " → " + b.name);
}
```

This query follows `friend` references between captured `Person` objects and
returns each matched pair.
`-[:friend]->` follows the `friend` field between captured `Person` objects
and returns each matched pair. The loop casts those cells back to `Person`
and prints the names.

## Using ϵStore in a Maven Project

Expand Down
15 changes: 11 additions & 4 deletions estore/src/test/java/org/estore/DbMetadataTest/H2MetadataTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@
public class H2MetadataTest {
private Connection h2Conn1;
private Estore estore1;
private boolean profileFlag;

@BeforeEach
public void setup() throws Exception {
String unsafeOpt = System.getProperty("useUnsafe");
Boolean unsafeFlag = (unsafeOpt != null) && (unsafeOpt.equals("true"));
String profileOpt = System.getProperty("profile");
Boolean profileFlag = (profileOpt != null) && (profileOpt.equals("true"));
profileFlag = (profileOpt != null) && (profileOpt.equals("true"));

estore1 =
new Estore(
Expand Down Expand Up @@ -111,7 +112,9 @@ public void testCatalogsJDBCRepeat() throws Exception {
long t1 = System.nanoTime();
DatabaseMetaData meta1 = h2Conn1.getMetaData();
res1 = meta1.getCatalogs();
// System.out.println("Total Query Time : " + (System.nanoTime() - t1));
if (profileFlag) {
System.out.println("Total Query Time : " + (System.nanoTime() - t1));
}
}

Set<String> catalogs = new HashSet<>();
Expand Down Expand Up @@ -204,7 +207,9 @@ public void testSchemasJDBCRepeat() throws Exception {
long t1 = System.nanoTime();
DatabaseMetaData meta1 = h2Conn1.getMetaData();
res1 = meta1.getSchemas();
// System.out.println("Total Query Time : " + (System.nanoTime() - t1));
if (profileFlag) {
System.out.println("Total Query Time : " + (System.nanoTime() - t1));
}
}

Set<String> schemas = new HashSet<>();
Expand Down Expand Up @@ -320,7 +325,9 @@ public void testTablesJDBCRepeat() throws Exception {
long t1 = System.nanoTime();
DatabaseMetaData meta1 = h2Conn1.getMetaData();
res1 = meta1.getTables(null, "PUBLIC", "%", new String[] {"TABLE"});
// System.out.println("Total Query Time : " + (System.nanoTime() - t1));
if (profileFlag) {
System.out.println("Total Query Time : " + (System.nanoTime() - t1));
}
}

Set<String> tables = new HashSet<>();
Expand Down
33 changes: 17 additions & 16 deletions estore/src/test/java/org/estore/eval/ldbc/finbench/Fin001Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,111 +33,112 @@ public void setupData() throws Exception {
readDataSet();
}

private void printQueryTime(String queryName, long startNanos) {
String profileOpt = System.getProperty("profile");
if (profileOpt != null && profileOpt.equals("true")) {
System.out.println(queryName);
System.out.println(
"Time: " + ((float) (System.nanoTime() - startNanos)) / 1_000_000.0 + "ms");
}
}

@CompileQuery
@Test
public void testTw1() {
// System.out.println("Tw1");
long t1 = System.nanoTime();
Table result =
estore.query(
"CREATE (:`org.estore.eval.ldbc.finbench.util.Person` {personId: 1, personName:"
+ " 'George'})-[:Own]->(:`org.estore.eval.ldbc.finbench.util.Account`"
+ " {accountId: 1020342322, createTime: '26th March', isBlocked: False,"
+ " accountType: 'brokerage account'})");
// System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000.0 + "ms");
printQueryTime("Tw1", t1);
}

@CompileQuery
@Test
public void testTw2() {
// System.out.println("Tw2");
long t1 = System.nanoTime();
Table result =
estore.query(
"CREATE (:`org.estore.eval.ldbc.finbench.util.Company` {companyId: 12345,"
+ " companyName: 'Rand'})-[:Own]->(:`org.estore.eval.ldbc.finbench.util.Account`"
+ " {accountId: 1213243435, createTime: 'February 5th', isBlocked: False,"
+ " accountType: 'brokerage account'})");
// System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000.0 + "ms");
printQueryTime("Tw2", t1);
}

@CompileQuery
@Test
public void testTw3() {
// System.out.println("Tw3");
long t1 = System.nanoTime();
Table result =
estore.query(
" MATCH (dst:`org.estore.eval.ldbc.finbench.util.Account` {accountId:"
+ " 4619004367821865972}), (src:`org.estore.eval.ldbc.finbench.util.Account`"
+ " {accountId: 99079191802151398}) CREATE (dst)-[:Transfer]->(src)");
// System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000.0 + "ms");
printQueryTime("Tw3", t1);
}

@CompileQuery
@Test
public void testTw4() {
// System.out.println("Tw4");
long t1 = System.nanoTime();
Table result =
estore.query(
" MATCH (dst:`org.estore.eval.ldbc.finbench.util.Account` {accountId:"
+ " 4619004367821865972, accountType:'card'}),"
+ " (src:`org.estore.eval.ldbc.finbench.util.Account` {accountId:"
+ " 99079191802151398}) CREATE (dst)-[:Withdraw]->(src)");
// System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000.0 + "ms");
printQueryTime("Tw4", t1);
}

@CompileQuery
@Test
public void testTw8() {
// System.out.println("Tw8");
long t1 = System.nanoTime();
Table result =
estore.query(
"MATCH (acc:`org.estore.eval.ldbc.finbench.util.Account` {accountId:"
+ " 4700350636091245930}), (loan:`org.estore.eval.ldbc.finbench.util.Loan`"
+ " {loanId: 4684025087442027461}) CREATE (loan)-[:Deposit]->(acc)");
// System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000.0 + "ms");
printQueryTime("Tw8", t1);
}

@CompileQuery
@Test
public void testTw9() {
// System.out.println("Tw9");
long t1 = System.nanoTime();
Table result =
estore.query(
"MATCH (acc:`org.estore.eval.ldbc.finbench.util.Account` {accountId:"
+ " 4700350636091245930}), (loan:`org.estore.eval.ldbc.finbench.util.Loan`"
+ " {loanId: 4684025087442027461}) CREATE (acc)-[:Repay]->(loan)");
// System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000.0 + "ms");
printQueryTime("Tw9", t1);
}

@CompileQuery
@Test
public void testTw13() {
// System.out.println("Tw13");
long t1 = System.nanoTime();
Table result =
estore.query(
"MATCH (p1:`org.estore.eval.ldbc.finbench.util.Person` {personId: 2199023255767}),"
+ " (p2:`org.estore.eval.ldbc.finbench.util.Person` {personId: 10995116278183})"
+ " CREATE (p1)<-[:Guarantee]-(p2)");
// System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000.0 + "ms");
printQueryTime("Tw13", t1);
}

@CompileQuery
@Test
public void testTsr1() {
// System.out.println("Tsr1");
long t1 = System.nanoTime();
Table result =
estore.query(
"MATCH (account:`org.estore.eval.ldbc.finbench.util.Account` {accountId:"
+ " 4700350636091245930}) RETURN account.createTime, account.isBlocked,"
+ " account.accountType");
// System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000.0 + "ms");
printQueryTime("Tsr1", t1);
assertEquals(result.get("account.createTime").get(0), "2020-11-11 18:44:24.021");
assertEquals(result.get("account.isBlocked").get(0), false);
assertEquals(result.get("account.accountType").get(0), "certificate of deposit");
Expand Down
36 changes: 18 additions & 18 deletions estore/src/test/java/org/estore/eval/ldbc/snb/Snb01Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,52 +32,57 @@ public void setupData() throws Exception {
readDataSet();
}

private void printQueryTime(String queryName, long startNanos) {
String profileOpt = System.getProperty("profile");
if (profileOpt != null && profileOpt.equals("true")) {
System.out.println(queryName);
System.out.println(
"Time: " + ((float) (System.nanoTime() - startNanos)) / 1_000_000.0 + "ms");
}
}

@CompileQuery
@Test
public void testInteractiveDeleteQuery2() {
// System.out.println("InteractiveDeleteQuery2");
long t1 = System.nanoTime();
Table result =
estore.query(
"MATCH (m:`org.estore.eval.ldbc.snb.util.Person`"
+ "{id:10995116278291})-[likes:LIKES2]->(:`org.estore.eval.ldbc.snb.util.Post`"
+ "{id:343597383821}) DELETE likes RETURN COUNT(m)");
// System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000.0 + "ms");
printQueryTime("InteractiveDeleteQuery2", t1);
assertEquals(result.get("COUNT(m)").get(0), 1);
}

@CompileQuery
@Test
public void testInteractiveDeleteQuery3() {
// System.out.println("InteractiveDeleteQuery3");
long t1 = System.nanoTime();
Table result =
estore.query(
"MATCH (m:`org.estore.eval.ldbc.snb.util.Person`"
+ " {id:19791209300608})-[likes:LIKES1]->(:`org.estore.eval.ldbc.snb.util.Comment`"
+ " {id:549755814421}) DELETE likes RETURN COUNT(m)");
// System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000 + "ms");
printQueryTime("InteractiveDeleteQuery3", t1);
assertEquals(result.get("COUNT(m)").get(0), 1);
}

@CompileQuery
@Test
public void testInteractiveDeleteQuery5() {
// System.out.println("InteractiveDeleteQuery5");
long t1 = System.nanoTime();
Table result =
estore.query(
"MATCH (m:`org.estore.eval.ldbc.snb.util.Forum`"
+ " {id:481036337162})-[hasMember:HAS_MEMBER]->(:`org.estore.eval.ldbc.snb.util.Person`"
+ " {id:2199023256077}) DELETE hasMember RETURN COUNT(m)");
// System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000 + "ms");
printQueryTime("InteractiveDeleteQuery5", t1);
assertEquals(result.get("COUNT(m)").get(0), 1);
}

@CompileQuery
@Test
public void testInteractiveShortQuery1() {
// System.out.println("InteractiveShortQuery1");
long t1 = System.nanoTime();
Table result =
estore.query(
Expand All @@ -86,7 +91,7 @@ public void testInteractiveShortQuery1() {
+ " RETURN n.firstName AS firstName, n.lastName AS lastName, n.birthday AS"
+ " birthday, n.locationIP AS locationIP, n.browserUsed AS browserUsed, p.id AS"
+ " cityId, n.gender AS gender, n.creationDate AS creationDate");
// System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000 + "ms");
printQueryTime("InteractiveShortQuery1", t1);
assertEquals(result.get("birthday").get(0), 579484800000L);
assertEquals(result.get("firstName").get(0), "Min-Jung");
assertEquals(result.get("lastName").get(0), "Park");
Expand All @@ -100,14 +105,13 @@ public void testInteractiveShortQuery1() {
@CompileQuery
@Test
public void testInteractiveShortQuery5() {
// System.out.println("InteractiveShortQuery5");
long t1 = System.nanoTime();
Table result =
estore.query(
"MATCH (m:`org.estore.eval.ldbc.snb.util.Comment`"
+ " {id:206158430603})-[:HAS_CREATOR]->(p:`org.estore.eval.ldbc.snb.util.Person`)"
+ " RETURN p.id AS personId, p.firstName AS firstName, p.lastName AS lastName");
// System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000 + "ms");
printQueryTime("InteractiveShortQuery5", t1);
assertEquals(result.get("firstName").get(0), "Rudolf");
assertEquals(result.get("lastName").get(0), "Engel");
assertEquals(result.get("personId").get(0), 2199023256437L);
Expand All @@ -116,56 +120,52 @@ public void testInteractiveShortQuery5() {
@CompileQuery
@Test
public void testInteractiveUpdateQuery2() {
// System.out.println("InteractiveUpdateQuery2");
long t1 = System.nanoTime();
Table result =
estore.query( // error here
"MATCH (person:`org.estore.eval.ldbc.snb.util.Person` {id:10995116278291}),"
+ " (post:`org.estore.eval.ldbc.snb.util.Post` {id:481036337280}) CREATE"
+ " (person)-[r:LIKES2]->(post) RETURN COUNT(r)");
// System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000 + "ms");
printQueryTime("InteractiveUpdateQuery2", t1);
assertEquals(result.get("COUNT(r)").get(0), 1);
}

@CompileQuery
@Test
public void testInteractiveUpdateQuery3() {
// System.out.println("InteractiveUpdateQuery3");
long t1 = System.nanoTime();
Table result =
estore.query(
"MATCH (person:`org.estore.eval.ldbc.snb.util.Person` {id:19791209301454}),"
+ " (comment:`org.estore.eval.ldbc.snb.util.Comment` {id:481036337631}) CREATE"
+ " (person)-[r:LIKES1]->(comment) RETURN COUNT(r)");
// System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000 + "ms");
printQueryTime("InteractiveUpdateQuery3", t1);
assertEquals(result.get("COUNT(r)").get(0), 1);
}

@CompileQuery
@Test
public void testInteractiveUpdateQuery5() {
// System.out.println("InteractiveUpdateQuery5");
long t1 = System.nanoTime();
Table result =
estore.query(
"MATCH (f:`org.estore.eval.ldbc.snb.util.Forum` {id:549755813984}),"
+ " (p:`org.estore.eval.ldbc.snb.util.Person` {id:19791209300852}) CREATE"
+ " (f)-[r:HAS_MEMBER]->(p) RETURN COUNT(r)");
// System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000 + "ms");
printQueryTime("InteractiveUpdateQuery5", t1);
assertEquals(result.get("COUNT(r)").get(0), 1);
}

@CompileQuery
@Test
public void testInteractiveUpdateQuery8() {
// System.out.println("InteractiveUpdateQuery8");
long t1 = System.nanoTime();
Table result =
estore.query(
"MATCH (p1:`org.estore.eval.ldbc.snb.util.Person` {id:4398046512167}),"
+ " (p2:`org.estore.eval.ldbc.snb.util.Person` {id:2199023256816}) CREATE"
+ " (p1)-[r:KNOWS]->(p2) RETURN COUNT(r)");
// System.out.println("Time: " + ((float) (System.nanoTime() - t1)) / 1_000_000 + "ms");
printQueryTime("InteractiveUpdateQuery8", t1);
assertEquals(result.get("COUNT(r)").get(0), 1);
}

Expand Down
5 changes: 5 additions & 0 deletions estore/src/test/java/org/estore/example/Person.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,9 @@ public Person(String name, int age, Person friend) {
this.age = age;
this.friend = friend;
}

@Override
public String toString() {
return name + " (" + age + ")";
}
}
Loading
Loading