Skip to content

Commit

Permalink
pattern matching - added support for 'while' condition and deep trave…
Browse files Browse the repository at this point in the history
…rsal
  • Loading branch information
luigidellaquila committed Jul 22, 2015
1 parent e6ce341 commit 12dc806
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 63 deletions.
12 changes: 4 additions & 8 deletions core/src/main/grammar/OrientSQL.jjt
Expand Up @@ -2995,14 +2995,6 @@ OMatchFilterItem MatchFilterItem():
<AS> <COLON> jjtThis.alias = Identifier()
)
|
(
<MINDEPTH> <COLON> jjtThis.minDepth = Integer()
)
|
(
<MAXDEPTH> <COLON> jjtThis.maxDepth = Integer()
)
|
(
<WHERE> <COLON> <LPAREN>
(
Expand All @@ -3018,6 +3010,10 @@ OMatchFilterItem MatchFilterItem():
)
<RPAREN>
)
|
(
<MAXDEPTH> <COLON> jjtThis.maxDepth = Integer()
)
)
{ return jjtThis; }
}
Expand Up @@ -9,7 +9,6 @@ public class OMatchFilterItem extends SimpleNode {
protected OWhereClause filter;
protected OWhereClause whileCondition;
protected OArrayRangeSelector depth;
protected OInteger minDepth;
protected OInteger maxDepth;

public OMatchFilterItem(int id) {
Expand Down Expand Up @@ -38,10 +37,6 @@ public String toString() {
return "as: " + alias;
}

if (minDepth != null) {
return "mindepth: " + minDepth;
}

if (maxDepth != null) {
return "maxdepth: " + maxDepth;
}
Expand Down
Expand Up @@ -441,17 +441,48 @@ private String calculateNextRoot(Pattern pattern, MatchContext ctx) {
}

private Object executeTraversal(MatchContext matchContext, OCommandContext iCommandContext, PatternEdge outEdge) {
Iterable<OIdentifiable> queryResult = (Iterable) outEdge.item.method.execute(matchContext.matched.get(matchContext.root),
iCommandContext);
if (outEdge.item.filter == null || outEdge.item.filter.getFilter() == null) {
return queryResult;
}
return executeTraversal(matchContext, iCommandContext, outEdge, matchContext.matched.get(matchContext.root), 0);
}

private Iterable<OIdentifiable> executeTraversal(MatchContext matchContext, OCommandContext iCommandContext, PatternEdge outEdge,
OIdentifiable startingPoint, int depth) {

OWhereClause filter = outEdge.item.filter.getFilter();
OWhereClause whileCondition = outEdge.item.filter.getWhileCondition();

Set<OIdentifiable> result = new HashSet<OIdentifiable>();

for (OIdentifiable origin : queryResult) {
if (filter.matchesFilters(origin, iCommandContext)) {
result.add(origin);
if (whileCondition == null) {// in this case starting point is not returned and only one level depth is evaluated
Iterable<OIdentifiable> queryResult = (Iterable) outEdge.item.method.execute(startingPoint, iCommandContext);
if (outEdge.item.filter == null || outEdge.item.filter.getFilter() == null) {
return queryResult;
}

for (OIdentifiable origin : queryResult) {
if (filter == null || filter.matchesFilters(origin, iCommandContext)) {
result.add(origin);
}
}
} else {// in this case also zero level (starting point) is considered and traversal depth is given by the while condition
iCommandContext.setVariable("$depth", depth);
if (whileCondition.matchesFilters(startingPoint, iCommandContext)) {
if (filter == null || filter.matchesFilters(startingPoint, iCommandContext)) {
result.add(startingPoint);
}
Iterable<OIdentifiable> queryResult = (Iterable) outEdge.item.method.execute(startingPoint, iCommandContext);

for (OIdentifiable origin : queryResult) {
// TODO optimize checking maxDepth
// TODO consider break strategies (eg. re-traverse nodes)
Iterable<OIdentifiable> subResult = executeTraversal(matchContext, iCommandContext, outEdge, origin, depth + 1);
if (subResult instanceof Collection) {
result.addAll((Collection<? extends OIdentifiable>) subResult);
} else {
for (OIdentifiable i : subResult) {
result.add(i);
}
}
}
}
}
return result;
Expand Down
Expand Up @@ -42,7 +42,11 @@ public Object execute(OIdentifiable iCurrentRecord, OCommandContext ctx) {
return iCurrentRecord;
}
if (identifier != null) {
return ((ODocument) iCurrentRecord.getRecord()).field(identifier.getValue());
String varName = identifier.getValue();
if (ctx.getVariable(varName) != null) {
return ctx.getVariable(varName);
}
return ((ODocument) iCurrentRecord.getRecord()).field(varName);
}
if (recordAttribute != null) {
return ((ODocument) iCurrentRecord.getRecord()).field(recordAttribute.name);
Expand Down
Expand Up @@ -8343,7 +8343,6 @@ final public OMatchFilter MatchFilter() throws ParseException {
case WHILE:
case AS:
case MAXDEPTH:
case MINDEPTH:
case CLASS:
case CLASSES:
lastItem = MatchFilterItem();
Expand Down Expand Up @@ -8418,16 +8417,6 @@ final public OMatchFilterItem MatchFilterItem() throws ParseException {
jj_consume_token(COLON);
jjtn000.alias = Identifier();
break;
case MINDEPTH:
jj_consume_token(MINDEPTH);
jj_consume_token(COLON);
jjtn000.minDepth = Integer();
break;
case MAXDEPTH:
jj_consume_token(MAXDEPTH);
jj_consume_token(COLON);
jjtn000.maxDepth = Integer();
break;
case WHERE:
jj_consume_token(WHERE);
jj_consume_token(COLON);
Expand All @@ -8442,6 +8431,11 @@ final public OMatchFilterItem MatchFilterItem() throws ParseException {
jjtn000.whileCondition = WhereClause();
jj_consume_token(RPAREN);
break;
case MAXDEPTH:
jj_consume_token(MAXDEPTH);
jj_consume_token(COLON);
jjtn000.maxDepth = Integer();
break;
default:
jj_la1[212] = jj_gen;
jj_consume_token(-1);
Expand Down Expand Up @@ -9160,12 +9154,10 @@ private boolean jj_2_98(int xla) {
finally { jj_save(97, xla); }
}

private boolean jj_3R_469() {
if (jj_scan_token(WHILE)) return true;
private boolean jj_3R_468() {
if (jj_scan_token(MAXDEPTH)) return true;
if (jj_scan_token(COLON)) return true;
if (jj_scan_token(LPAREN)) return true;
if (jj_3R_241()) return true;
if (jj_scan_token(RPAREN)) return true;
if (jj_3R_45()) return true;
return false;
}

Expand All @@ -9185,22 +9177,15 @@ private boolean jj_3_31() {
return false;
}

private boolean jj_3R_468() {
if (jj_scan_token(WHERE)) return true;
private boolean jj_3R_467() {
if (jj_scan_token(WHILE)) return true;
if (jj_scan_token(COLON)) return true;
if (jj_scan_token(LPAREN)) return true;
if (jj_3R_241()) return true;
if (jj_scan_token(RPAREN)) return true;
return false;
}

private boolean jj_3R_467() {
if (jj_scan_token(MAXDEPTH)) return true;
if (jj_scan_token(COLON)) return true;
if (jj_3R_45()) return true;
return false;
}

private boolean jj_3R_238() {
if (jj_scan_token(CLUSTER)) return true;
if (jj_3R_62()) return true;
Expand All @@ -9224,9 +9209,11 @@ private boolean jj_3R_115() {
}

private boolean jj_3R_466() {
if (jj_scan_token(MINDEPTH)) return true;
if (jj_scan_token(WHERE)) return true;
if (jj_scan_token(COLON)) return true;
if (jj_3R_45()) return true;
if (jj_scan_token(LPAREN)) return true;
if (jj_3R_241()) return true;
if (jj_scan_token(RPAREN)) return true;
return false;
}

Expand Down Expand Up @@ -9290,10 +9277,7 @@ private boolean jj_3R_459() {
jj_scanpos = xsp;
if (jj_3R_467()) {
jj_scanpos = xsp;
if (jj_3R_468()) {
jj_scanpos = xsp;
if (jj_3R_469()) return true;
}
if (jj_3R_468()) return true;
}
}
}
Expand Down Expand Up @@ -9353,12 +9337,12 @@ private boolean jj_3R_453() {
return false;
}

private boolean jj_3R_472() {
private boolean jj_3R_471() {
if (jj_3R_453()) return true;
return false;
}

private boolean jj_3R_471() {
private boolean jj_3R_470() {
if (jj_3R_461()) return true;
return false;
}
Expand Down Expand Up @@ -9398,15 +9382,15 @@ private boolean jj_3R_462() {
Token xsp;
while (true) {
xsp = jj_scanpos;
if (jj_3R_471()) { jj_scanpos = xsp; break; }
if (jj_3R_470()) { jj_scanpos = xsp; break; }
}
if (jj_scan_token(RPAREN)) return true;
xsp = jj_scanpos;
if (jj_3R_472()) jj_scanpos = xsp;
if (jj_3R_471()) jj_scanpos = xsp;
return false;
}

private boolean jj_3R_470() {
private boolean jj_3R_469() {
if (jj_3R_453()) return true;
return false;
}
Expand All @@ -9420,7 +9404,7 @@ private boolean jj_3R_461() {
if (jj_3R_77()) return true;
Token xsp;
xsp = jj_scanpos;
if (jj_3R_470()) jj_scanpos = xsp;
if (jj_3R_469()) jj_scanpos = xsp;
return false;
}

Expand Down Expand Up @@ -13298,7 +13282,7 @@ private static void jj_la1_init_0() {
jj_la1_0 = new int[] {0xffffff60,0x7f10000,0x0,0x0,0x60,0x100,0x2080,0x0,0x60,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x47f10000,0x0,0x20000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f10000,0x0,0x40000,0x0,0x0,0x0,0x0,0x0,0x0,0x20000,0x0,0x0,0x0,0x20000,0x0,0x0,0x0,0x0,0x7f10000,0x0,0x0,0x7f10000,0x0,0x0,0x7f10000,0x10000,0x20000,0x0,0x0,0x0,0x7f10000,0x20000,0x0,0x0,0x0,0x7f10000,0x20000,0x0,0x7f10000,0x20000,0x0,0x7f10000,0xfe00000,0x4000,0x0,0x47f10000,0x0,0x20000,0x0,0x0,0x0,0x0,0x0,0x3000000,0x8400000,0x0,0x0,0xfe00000,0x0,0x0,0x0,0x0,0x7f10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8000,0x20,0x2008020,0x0,0x0,0x0,0x0,0x0,0x7f10000,0x0,0x0,0x7f10000,0x0,0x0,0x7f10000,0x2208020,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x47f10000,0x0,0x47f10000,0x0,0x0,0x0,0x0,0x40000000,0x0,0x0,0x0,0x47f10020,0x0,0x7f10000,0x0,0x40,0x0,0xc0,0x7f10000,0x0,0x7f10000,0x0,0x20000000,0x10000000,0x47f10000,0x0,0x0,0x0,0x7f10000,0x0,0x47f10000,0x0,0x47f10000,0x0,0x47f10000,0x0,0x7f10000,0x7f10000,0x0,0x0,0x7f10000,0x0,0x0,0x0,0x7f10000,0x0,0x0,0x7f10000,0x0,0x0,0x7f10000,0x0,0x0,0x0,0x7f10000,0x0,0x0,0x7f10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x47f10000,0x7f10000,0x0,0x0,0x0,0x0,0x7f10000,0x0,0x47f10000,0x7f10000,0x0,0x7f10000,0x7f10000,0x0,0x0,0x0,0x0,0x0,0x0,0x60000,0x60000,};
}
private static void jj_la1_init_1() {
jj_la1_1 = new int[] {0x3fffffff,0xce008023,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x40000,0x10000000,0x400,0x40,0x4000,0x200000,0x80000,0xce008023,0x40000,0x0,0x2,0x1,0x10000000,0x8,0x30,0x38,0x38,0x400,0x40,0x4000,0x200000,0x80000,0x0,0xce008023,0x20000000,0x0,0x8,0x1800000,0x400000,0x0,0x0,0x800,0x0,0x8,0x100000,0x800,0x0,0x8,0x0,0x0,0x0,0xce008023,0x0,0x0,0xce008023,0x0,0x0,0xce008023,0x0,0x0,0x8,0x0,0x0,0xce008023,0x0,0x8,0x0,0x0,0xce008023,0x0,0x8,0xce008023,0x0,0x8,0xce008023,0x0,0x0,0x3000,0xce008023,0x800,0x0,0x4000,0x8,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xce008023,0x800,0x100000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x800,0x0,0x0,0x800,0x0,0xce008023,0x0,0x0,0xce008023,0x0,0x0,0xce008023,0x0,0x20000,0x10000,0x0,0x0,0x100,0x0,0x0,0x0,0x0,0xce008023,0x0,0xce008023,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xce008023,0x0,0xce008023,0x0,0x0,0x0,0x0,0xce008023,0x0,0xce008023,0x0,0x0,0x0,0xce008023,0x0,0xe000000,0x0,0xce008023,0x0,0xce008023,0x0,0xce008023,0x0,0xce008023,0xe000000,0xce008023,0xce008023,0x0,0x0,0xce008023,0x280,0x280,0x0,0xce008023,0x280,0x280,0xce008023,0x0,0x0,0xce008023,0x280,0x280,0x0,0xce008023,0x280,0x280,0xce008023,0x0,0x0,0x0,0x0,0x0,0x30,0x0,0xce008023,0xce008023,0x0,0x0,0x0,0x0,0xce008023,0x0,0xce008023,0xce008023,0x0,0xce008023,0xce008023,0x0,0x0,0x0,0x0,0x0,0x0,0xe0000100,0xe0000100,};
jj_la1_1 = new int[] {0x3fffffff,0xce008023,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x40000,0x10000000,0x400,0x40,0x4000,0x200000,0x80000,0xce008023,0x40000,0x0,0x2,0x1,0x10000000,0x8,0x30,0x38,0x38,0x400,0x40,0x4000,0x200000,0x80000,0x0,0xce008023,0x20000000,0x0,0x8,0x1800000,0x400000,0x0,0x0,0x800,0x0,0x8,0x100000,0x800,0x0,0x8,0x0,0x0,0x0,0xce008023,0x0,0x0,0xce008023,0x0,0x0,0xce008023,0x0,0x0,0x8,0x0,0x0,0xce008023,0x0,0x8,0x0,0x0,0xce008023,0x0,0x8,0xce008023,0x0,0x8,0xce008023,0x0,0x0,0x3000,0xce008023,0x800,0x0,0x4000,0x8,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xce008023,0x800,0x100000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x800,0x0,0x0,0x800,0x0,0xce008023,0x0,0x0,0xce008023,0x0,0x0,0xce008023,0x0,0x20000,0x10000,0x0,0x0,0x100,0x0,0x0,0x0,0x0,0xce008023,0x0,0xce008023,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xce008023,0x0,0xce008023,0x0,0x0,0x0,0x0,0xce008023,0x0,0xce008023,0x0,0x0,0x0,0xce008023,0x0,0xe000000,0x0,0xce008023,0x0,0xce008023,0x0,0xce008023,0x0,0xce008023,0xe000000,0xce008023,0xce008023,0x0,0x0,0xce008023,0x280,0x280,0x0,0xce008023,0x280,0x280,0xce008023,0x0,0x0,0xce008023,0x280,0x280,0x0,0xce008023,0x280,0x280,0xce008023,0x0,0x0,0x0,0x0,0x0,0x30,0x0,0xce008023,0xce008023,0x0,0x0,0x0,0x0,0xce008023,0x0,0xce008023,0xce008023,0x0,0xce008023,0xce008023,0x0,0x0,0x0,0x0,0x0,0x0,0xa0000100,0xa0000100,};
}
private static void jj_la1_init_2() {
jj_la1_2 = new int[] {0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x57611007,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x40000007,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000,0x40001000,0x1,0x0,0x1000,0x44001001,0x0,0x1000,0x44001001,0x0,0x0,0x0,0x0,0x1000,0x44001001,0x0,0x0,0x0,0x1000,0x44001001,0x0,0x0,0x1,0x0,0x0,0x4001001,0x0,0x0,0x0,0x57611007,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x40000000,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4000000,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x1000,0x44001001,0x0,0x1000,0x44001001,0x4000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x57611007,0x0,0x57611007,0x2,0x0,0x40000000,0x0,0x0,0x13000000,0x0,0x0,0x57611007,0x600000,0x40611007,0x0,0x0,0x4000000,0x0,0x44001007,0x0,0x1,0x0,0x0,0x0,0x57611007,0x3000000,0x0,0x0,0x400001,0x0,0x57611007,0x0,0x57611007,0x0,0x57611007,0x0,0x44611007,0x44611007,0x600000,0x40000000,0x1005,0x0,0x0,0x40000000,0x1005,0x0,0x0,0x4001005,0x0,0x40000000,0x1005,0x0,0x0,0x40000000,0x1005,0x0,0x0,0x4001005,0x0,0x0,0x1000,0x1000,0x1000,0x0,0x0,0x57611007,0x40000001,0x40000000,0x0,0x0,0x0,0x40000001,0x0,0x57611007,0x600001,0x0,0x600001,0x600001,0x4000000,0x4000000,0x10000000,0x0,0x10000000,0x0,0x1,0x1,};
Expand Down
Expand Up @@ -77,7 +77,6 @@ public void testFilterTypes() {
query.append(" class: 'v', ");
query.append(" as: foo, ");
query.append(" where: (name = 'foo' and surname = 'bar' or aaa in [1,2,3]), ");
query.append(" minDepth: 0, ");
query.append(" maxDepth: 10 ");
query.append("} return foo");
System.out.println(query);
Expand All @@ -91,7 +90,6 @@ public void testFilterTypes2() {
query.append(" classes: ['V', 'E'], ");
query.append(" as: foo, ");
query.append(" where: (name = 'foo' and surname = 'bar' or aaa in [1,2,3]), ");
query.append(" minDepth: 0, ");
query.append(" maxDepth: 10 ");
query.append("} return foo");
System.out.println(query);
Expand All @@ -102,7 +100,7 @@ public void testFilterTypes2() {
public void testMultiPath() {
StringBuilder query = new StringBuilder();
query.append("MATCH {}");
query.append(" (.out().in(){class:'v'}.both('Foo')){minDepth: 3}.out() return foo");
query.append(" (.out().in(){class:'v'}.both('Foo')){maxDepth: 3}.out() return foo");
System.out.println(query);
checkRightSyntax(query.toString());
}
Expand Down
Expand Up @@ -124,6 +124,32 @@ public void testFriendsWithName() throws Exception {
assertEquals("n2", qResult.get(0).field("name"));
}

@Test
public void testWhile() throws Exception {

List<ODocument> qResult = db
.command(
new OCommandSQL(
"select friend.name as name from (match {class:Person, where:(name = 'n1')}.out('Friend'){as:friend, while: ($depth < 2)} return friend)"))
.execute();
assertEquals(3, qResult.size());

qResult = db
.command(
new OCommandSQL(
"select friend.name as name from (match {class:Person, where:(name = 'n1')}.out('Friend'){as:friend, while: ($depth < 2), where: ($depth=1) } return friend)"))
.execute();
assertEquals(2, qResult.size());

qResult = db
.command(
new OCommandSQL(
"select friend.name as name from (match {class:Person, where:(name = 'n1')}.out('Friend'){as:friend, while: (true) } return friend)"))
.execute();
assertEquals(6, qResult.size());

}

private long indexUsages(ODatabaseDocumentTx db) {
final long oldIndexUsage;
try {
Expand Down

0 comments on commit 12dc806

Please sign in to comment.