Author: thomasm
Date: Fri Nov 4 10:04:22 2016
New Revision: 1767999
URL: http://svn.apache.org/viewvc?rev=1767999&view=rev
Log:
OAK-5064 XPath: chained conditions and union bugfix
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/XPathTest.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java?rev=1767999&r1=1767998&r2=1767999&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
Fri Nov 4 10:04:22 2016
@@ -298,9 +298,11 @@ public class XPathToSQL2Converter {
throw getSyntaxError();
}
if (readIf("[")) {
- Expression c = parseConstraint();
- currentSelector.condition =
Expression.and(currentSelector.condition, c);
- read("]");
+ do {
+ Expression c = parseConstraint();
+ currentSelector.condition =
Expression.and(currentSelector.condition, c);
+ read("]");
+ } while (readIf("["));
}
startOfQuery = false;
nextSelector(false);
@@ -1088,8 +1090,9 @@ public class XPathToSQL2Converter {
converter.read("(");
int level = 0;
ArrayList<String> parts = new ArrayList<String>();
+ int parseIndex;
while (true) {
- int parseIndex = converter.parseIndex;
+ parseIndex = converter.parseIndex;
if (converter.readIf("(")) {
level++;
} else if (converter.readIf(")") && level-- <= 0) {
@@ -1098,8 +1101,8 @@ public class XPathToSQL2Converter {
String or = partList.substring(lastOrIndex, lastParseIndex);
parts.add(or);
lastOrIndex = parseIndex;
- } else if (currentTokenType == END) {
- throw getSyntaxError("the query may not be empty");
+ } else if (converter.currentTokenType == END) {
+ throw getSyntaxError("empty query or missing ')'");
} else {
converter.read();
}
@@ -1107,7 +1110,7 @@ public class XPathToSQL2Converter {
}
String or = partList.substring(lastOrIndex, lastParseIndex);
parts.add(or);
- String end = partList.substring(lastParseIndex + 1);
+ String end = partList.substring(parseIndex);
Statement result = null;
for(String p : parts) {
String q = begin + p + end;
Modified:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/XPathTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/XPathTest.java?rev=1767999&r1=1767998&r2=1767999&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/XPathTest.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/XPathTest.java
Fri Nov 4 10:04:22 2016
@@ -18,6 +18,7 @@ package org.apache.jackrabbit.oak.query;
import static
org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent.INITIAL_CONTENT;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
import java.text.ParseException;
@@ -71,9 +72,58 @@ public class XPathTest {
"order by [c] " +
"option(traversal OK)");
}
+
+ @Test
+ public void chainedConditions() throws ParseException {
+ verify("/jcr:root/x[@a][@b][@c]",
+ "select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where [a] is not null " +
+ "and [b] is not null " +
+ "and [c] is not null " +
+ "and issamenode(a, '/x') " +
+ "/* xpath: /jcr:root/x[@a][@b][@c] */");
+ }
@Test
- public void test() throws ParseException {
+ public void union() throws ParseException {
+ try {
+ verify("(/jcr:root/x[@a][@b][@c]","");
+ fail();
+ } catch (ParseException e) {
+ // expected
+ }
+ verify("(/jcr:root/x[@a] | /jcr:root/y[@b])[@c]",
+ "select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where [a] is not null " +
+ "and [c] is not null " +
+ "and issamenode(a, '/x') " +
+ "/* xpath: /jcr:root/x[@a][@c] */ " +
+ "union select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where [b] is not null " +
+ "and [c] is not null " +
+ "and issamenode(a, '/y') " +
+ "/* xpath: /jcr:root/y[@b][@c] */");
+ verify("(/jcr:root/x | /jcr:root/y)",
+ "select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where issamenode(a, '/x') " +
+ "/* xpath: /jcr:root/x */ " +
+ "union select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where issamenode(a, '/y') " +
+ "/* xpath: /jcr:root/y */");
+ verify("(/jcr:root/x | /jcr:root/y )",
+ "select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where issamenode(a, '/x') " +
+ "/* xpath: /jcr:root/x */ " +
+ "union select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where issamenode(a, '/y') " +
+ "/* xpath: /jcr:root/y */");
verify("(/jcr:root/content//*[@a] | /jcr:root/lib//*[@b]) order by @c",
"select [jcr:path], [jcr:score], * " +
"from [nt:base] as a " +