You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by th...@apache.org on 2015/05/22 12:11:58 UTC
svn commit: r1681064 - in /jackrabbit/oak/branches/1.0/oak-core/src:
main/java/org/apache/jackrabbit/oak/query/xpath/
test/java/org/apache/jackrabbit/oak/query/
Author: thomasm
Date: Fri May 22 10:11:57 2015
New Revision: 1681064
URL: http://svn.apache.org/r1681064
Log:
OAK-2873 Performance problems with many "or" conditions
Modified:
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/query/LargeQueryTest.java
Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java?rev=1681064&r1=1681063&r2=1681064&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java Fri May 22 10:11:57 2015
@@ -318,12 +318,30 @@ abstract class Expression {
}
String commonLeft = getCommonLeftPart();
if (commonLeft == null) {
+ // the case:
+ // (other>0 or x=1) or x=2
+ // can be converted to:
+ // other>0 or (x=1 or x=2)
+ // which can then be optimized
+ if (left instanceof OrCondition) {
+ OrCondition orLeft = (OrCondition) left;
+ Expression l1 = orLeft.left;
+ Expression l2 = orLeft.right;
+ OrCondition orRight = new OrCondition(l2, right);
+ Expression o2 = orRight.optimize();
+ if (o2 != orRight) {
+ return new OrCondition(l1, o2);
+ }
+ }
return this;
}
// "@x = 1 or @x = 2" is converted to "@x in (1, 2)"
if (left instanceof InCondition) {
InCondition in = (InCondition) left;
in.list.addAll(right.getRight());
+ // return a new instance, because we changed
+ // the list
+ in = new InCondition(in.getLeft(), in.list);
return in;
}
ArrayList<Expression> list = new ArrayList<Expression>();
@@ -676,6 +694,8 @@ abstract class Expression {
final Selector selector;
final String name;
+ private String cacheString;
+ private boolean cacheOnlySelector;
/**
* If there was no "@" character in front of the property name. If that
@@ -692,6 +712,11 @@ abstract class Expression {
@Override
public String toString() {
+ if (cacheString != null) {
+ if (cacheOnlySelector == selector.onlySelector) {
+ return cacheString;
+ }
+ }
StringBuilder buff = new StringBuilder();
if (!selector.onlySelector) {
buff.append(selector.name).append('.');
@@ -701,7 +726,9 @@ abstract class Expression {
} else {
buff.append('[').append(name).append(']');
}
- return buff.toString();
+ cacheString = buff.toString();
+ cacheOnlySelector = selector.onlySelector;
+ return cacheString;
}
@Override
Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java?rev=1681064&r1=1681063&r2=1681064&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java Fri May 22 10:11:57 2015
@@ -432,7 +432,7 @@ public class XPathToSQL2Converter {
while (readIf("and")) {
a = new Expression.AndCondition(a, parseCondition());
}
- return a;
+ return a.optimize();
}
private Expression parseCondition() throws ParseException {
@@ -461,7 +461,7 @@ public class XPathToSQL2Converter {
}
a = parseCondition(e);
}
- return a;
+ return a.optimize();
}
private Expression.Condition parseCondition(Expression left) throws ParseException {
Modified: jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/query/LargeQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/query/LargeQueryTest.java?rev=1681064&r1=1681063&r2=1681064&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/query/LargeQueryTest.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/query/LargeQueryTest.java Fri May 22 10:11:57 2015
@@ -26,7 +26,7 @@ import org.junit.Test;
public class LargeQueryTest {
@Test
- public void test() throws ParseException {
+ public void testSimpleOr() throws ParseException {
StringBuilder buff = new StringBuilder("//*[");
StringBuilder buff2 = new StringBuilder(
"select [jcr:path], [jcr:score], * from [nt:base] as a where [x] in(");
@@ -46,4 +46,41 @@ public class LargeQueryTest {
buff2.append(" /* xpath: ").append(xpath).append(" */");
assertEquals(buff2.toString(), sql2);
}
+
+ @Test
+ public void testCombinedOr() throws ParseException {
+ StringBuilder buff = new StringBuilder("//*[");
+ StringBuilder buff2 = new StringBuilder(
+ "select [jcr:path], [jcr:score], * from [nt:base] as a where [x] in(");
+ int step = 111;
+ for (int i = 0; i < 5000; i++) {
+ if (i % step == 2) {
+ if (i > 0) {
+ buff.append(" or ");
+ }
+ buff.append("@x>").append(i);
+ buff2.append(") union select [jcr:path], [jcr:score], * from [nt:base] as a " +
+ "where [x] > ").append(i);
+ buff2.append(" union select [jcr:path], [jcr:score], * from [nt:base] as a " +
+ "where [x] in(");
+ } else {
+ if (i > 0) {
+ buff.append(" or ");
+ }
+ buff.append("@x=").append(i);
+ if (i > 0 && i % step != 3) {
+ buff2.append(", ");
+ }
+ buff2.append(i);
+ }
+ }
+ buff.append("]");
+ buff2.append(")");
+ String xpath = buff.toString();
+ XPathToSQL2Converter conv = new XPathToSQL2Converter();
+ String sql2 = conv.convert(xpath);
+ buff2.append(" /* xpath: ").append(xpath).append(" */");
+ assertEquals(buff2.toString(), sql2);
+ }
+
}