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 2016/04/27 12:18:27 UTC
svn commit: r1741199 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
test/java/org/apache/jackrabbit/oak/query/XPathTest.java
Author: thomasm
Date: Wed Apr 27 10:18:27 2016
New Revision: 1741199
URL: http://svn.apache.org/viewvc?rev=1741199&view=rev
Log:
OAK-4265 XPath: support limited form of "union" (work in progress)
Added:
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
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=1741199&r1=1741198&r2=1741199&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 Wed Apr 27 10:18:27 2016
@@ -17,6 +17,7 @@
package org.apache.jackrabbit.oak.query.xpath;
import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.query.xpath.Statement.UnionStatement;
import org.apache.jackrabbit.util.ISO9075;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -80,6 +81,12 @@ public class XPathToSQL2Converter {
* @throws ParseException if parsing fails
*/
public String convert(String query) throws ParseException {
+ Statement statement = convertToStatement(query);
+ statement = statement.optimize();
+ return statement.toString();
+ }
+
+ private Statement convertToStatement(String query) throws ParseException {
query = query.trim();
@@ -165,6 +172,7 @@ public class XPathToSQL2Converter {
currentSelector.isChild = true;
}
}
+ int startParseIndex = parseIndex;
if (shortcut) {
// "*" and so on are not allowed now
} else if (readIf("*")) {
@@ -238,6 +246,9 @@ public class XPathToSQL2Converter {
statement.addSelectColumn(p);
}
} while (readIf("|"));
+ if (!readIf(")")) {
+ return convertToUnion(query, statement, startParseIndex - 1);
+ }
read(")");
} else if (currentTokenType == IDENTIFIER) {
// path restriction
@@ -311,11 +322,7 @@ public class XPathToSQL2Converter {
where = Expression.and(where, s.condition);
}
statement.setWhere(where);
-
- statement = statement.optimize();
-
- return statement.toString();
-
+ return statement;
}
private void appendNodeName(String name) {
@@ -1021,6 +1028,57 @@ public class XPathToSQL2Converter {
}
return new ParseException("Query:\n" + query, index);
}
+
+ private Statement convertToUnion(String query, Statement statement,
+ int startParseIndex) throws ParseException {
+ int start = query.indexOf("(", startParseIndex);
+ String begin = query.substring(0, start);
+ XPathToSQL2Converter converter = new XPathToSQL2Converter();
+ String partList = query.substring(start);
+ converter.initialize(partList);
+ converter.read();
+ int lastParseIndex = converter.parseIndex;
+ int lastOrIndex = lastParseIndex;
+ converter.read("(");
+ int level = 0;
+ ArrayList<String> parts = new ArrayList<String>();
+ while (true) {
+ int parseIndex = converter.parseIndex;
+ if (converter.readIf("(")) {
+ level++;
+ } else if (converter.readIf(")") && level-- <= 0) {
+ break;
+ } else if (converter.readIf("|") && level == 0) {
+ String or = partList.substring(lastOrIndex, lastParseIndex);
+ parts.add(or);
+ lastOrIndex = parseIndex;
+ } else if (currentTokenType == END) {
+ throw getSyntaxError("the query may not be empty");
+ } else {
+ converter.read();
+ }
+ lastParseIndex = parseIndex;
+ }
+ String or = partList.substring(lastOrIndex, lastParseIndex);
+ parts.add(or);
+ String end = partList.substring(lastParseIndex + 1);
+ Statement result = null;
+ for(String p : parts) {
+ String q = begin + p + end;
+ converter = new XPathToSQL2Converter();
+ Statement stat = converter.convertToStatement(q);
+ if (result == null) {
+ result = stat;
+ } else {
+ UnionStatement union = new UnionStatement(result, stat);
+ union.orderList = stat.orderList;
+ result = union;
+ }
+ // can not use clear, because it is shared
+ stat.orderList = new ArrayList<Order>();
+ }
+ return result;
+ }
}
Added: 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=1741199&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/XPathTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/XPathTest.java Wed Apr 27 10:18:27 2016
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.query;
+
+import static org.apache.jackrabbit.JcrConstants.JCR_SYSTEM;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_NODE_TYPES;
+import static org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent.INITIAL_CONTENT;
+import static org.junit.Assert.assertEquals;
+
+import java.text.ParseException;
+
+import org.apache.jackrabbit.oak.query.xpath.XPathToSQL2Converter;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.junit.Test;
+
+/**
+ * Tests the XPathToSQL2Converter
+ */
+public class XPathTest {
+
+ private final NodeState types =
+ INITIAL_CONTENT.getChildNode(JCR_SYSTEM).getChildNode(JCR_NODE_TYPES);
+
+ @Test
+ public void test() throws ParseException {
+ verify("(/jcr:root/content//*[@a] | /jcr:root/lib//*[@b]) order by @c",
+ "select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where [a] is not null " +
+ "and isdescendantnode(a, '/content') " +
+ "/* xpath: /jcr:root/content//*[@a] " +
+ "order by @c */ " +
+ "union select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where [b] is not null " +
+ "and isdescendantnode(a, '/lib') " +
+ "/* xpath: /jcr:root/lib//*[@b] " +
+ "order by @c */ " +
+ "order by [c]");
+ verify("/jcr:root/(content|lib)/element(*, nt:base) order by @title",
+ "select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where ischildnode(a, '/content') " +
+ "/* xpath: /jcr:root/content/element(*, nt:base) " +
+ "order by @title */ " +
+ "union select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where ischildnode(a, '/lib') " +
+ "/* xpath: /jcr:root/lib/element(*, nt:base) " +
+ "order by @title */ " +
+ "order by [title]");
+ verify("/jcr:root/(content|lib)",
+ "select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where issamenode(a, '/content') " +
+ "/* xpath: /jcr:root/content */ " +
+ "union select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where issamenode(a, '/lib') " +
+ "/* xpath: /jcr:root/lib */");
+ verify("(/jcr:root/content|/jcr:root/lib)//*",
+ "select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where isdescendantnode(a, '/content') " +
+ "/* xpath: /jcr:root/content//* */ " +
+ "union select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where isdescendantnode(a, '/lib') " +
+ "/* xpath: /jcr:root/lib//* */");
+ verify("/jcr:root/content/(a|b|c)/thumbnails/*",
+ "select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where ischildnode(a, '/content/a/thumbnails') " +
+ "/* xpath: /jcr:root/content/a/thumbnails/* */ " +
+ "union select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where ischildnode(a, '/content/b/thumbnails') " +
+ "/* xpath: /jcr:root/content/b/thumbnails/* */ " +
+ "union select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where ischildnode(a, '/content/c/thumbnails') " +
+ "/* xpath: /jcr:root/content/c/thumbnails/* */");
+ verify("/jcr:root/(content|lib)//*[@a]",
+ "select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where [a] is not null " +
+ "and isdescendantnode(a, '/content') " +
+ "/* xpath: /jcr:root/content//*[@a] */ " +
+ "union select [jcr:path], [jcr:score], * " +
+ "from [nt:base] as a " +
+ "where [a] is not null " +
+ "and isdescendantnode(a, '/lib') " +
+ "/* xpath: /jcr:root/lib//*[@a] */");
+ }
+
+ private void verify(String xpath, String expectedSql2) throws ParseException {
+ String sql2 = new XPathToSQL2Converter().convert(xpath);
+ sql2 = formatSQL(sql2);
+ expectedSql2 = formatSQL(expectedSql2);
+ assertEquals(expectedSql2, sql2);
+ SQL2Parser p = new SQL2Parser(null, types, new QueryEngineSettings());
+ p.parse(sql2);
+ }
+
+ static String formatSQL(String sql) {
+ sql = sql.replace("\n", " ");
+ sql = sql.replaceAll(" from ", "\nfrom ");
+ sql = sql.replaceAll(" where ", "\nwhere ");
+ sql = sql.replaceAll(" and ", "\nand ");
+ sql = sql.replaceAll(" union ", "\nunion ");
+ sql = sql.replaceAll(" order by ", "\norder by ");
+ sql = sql.replaceAll(" \\/\\* ", "\n/* ");
+ return sql;
+ }
+
+}
Re: svn commit: r1741199 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
test/java/org/apache/jackrabbit/oak/query/XPathTest.java
Posted by Julian Reschke <ju...@gmx.de>.
On 2016-04-27 12:18, thomasm@apache.org wrote:
> Author: thomasm
> Date: Wed Apr 27 10:18:27 2016
> New Revision: 1741199
>
> URL: http://svn.apache.org/viewvc?rev=1741199&view=rev
> Log:
> OAK-4265 XPath: support limited form of "union" (work in progress)
> ...
This seems to break PropertyIndexQueryTest.xpath().
Best regards, Julian