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 2012/05/31 16:43:30 UTC
svn commit: r1344752 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/api/
main/java/org/apache/jackrabbit/oak/query/
main/java/org/apache/jackrabbit/oak/query/ast/
test/java/org/apache/jackrabbit/oak/query/ test/resources/o...
Author: thomasm
Date: Thu May 31 14:43:30 2012
New Revision: 1344752
URL: http://svn.apache.org/viewvc?rev=1344752&view=rev
Log:
OAK-28 Query implementation
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/QueryEngine.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/XPathToSQL2Converter.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElement.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ComparisonImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NodeNameImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeImpl.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/QueryTest.java
jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/queryXpathTest.txt
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/QueryEngine.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/QueryEngine.java?rev=1344752&r1=1344751&r2=1344752&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/QueryEngine.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/QueryEngine.java Thu May 31 14:43:30 2012
@@ -19,6 +19,7 @@ package org.apache.jackrabbit.oak.api;
import java.text.ParseException;
import java.util.List;
import java.util.Map;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
/**
* The query engine allows to parse and execute queries.
@@ -53,12 +54,14 @@ public interface QueryEngine {
* @param limit the maximum result set size
* @param offset the number of rows to skip
* @param bindings the bind variable value bindings
+ * @param namePathMapper the name and path mapper to use
* @return the result
* @throws ParseException if the statement could not be parsed
* @throws IllegalArgumentException if there was an error executing the query
*/
Result executeQuery(String statement, String language, ContentSession session,
- long limit, long offset, Map<String, CoreValue> bindings) throws ParseException;
+ long limit, long offset, Map<String, CoreValue> bindings,
+ NamePathMapper namePathMapper) throws ParseException;
// TODO pass namespace mapping
// TODO pass node type information (select * from [xyz] is supposed to return at least the mandatory columns for xyz)
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java?rev=1344752&r1=1344751&r2=1344752&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/Query.java Thu May 31 14:43:30 2012
@@ -23,6 +23,7 @@ import org.apache.jackrabbit.mk.api.Micr
import org.apache.jackrabbit.oak.api.ContentSession;
import org.apache.jackrabbit.oak.api.CoreValue;
import org.apache.jackrabbit.oak.api.CoreValueFactory;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.query.ast.AstVisitorBase;
import org.apache.jackrabbit.oak.query.ast.BindVariableValueImpl;
import org.apache.jackrabbit.oak.query.ast.ChildNodeImpl;
@@ -73,6 +74,7 @@ public class Query {
private boolean prepared;
private final CoreValueFactory valueFactory;
private ContentSession session;
+ private NamePathMapper namePathMapper;
Query(SourceImpl source, ConstraintImpl constraint, OrderingImpl[] orderings,
ColumnImpl[] columns, CoreValueFactory valueFactory) {
@@ -496,4 +498,12 @@ public class Query {
this.session = session;
}
+ public void setNamePathMapper(NamePathMapper namePathMapper) {
+ this.namePathMapper = namePathMapper;
+ }
+
+ public NamePathMapper getNamePathMapper() {
+ return namePathMapper;
+ }
+
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java?rev=1344752&r1=1344751&r2=1344752&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java Thu May 31 14:43:30 2012
@@ -26,6 +26,7 @@ import org.apache.jackrabbit.oak.api.Con
import org.apache.jackrabbit.oak.api.CoreValue;
import org.apache.jackrabbit.oak.api.CoreValueFactory;
import org.apache.jackrabbit.oak.api.QueryEngine;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
import org.apache.jackrabbit.oak.query.index.TraversingIndex;
import org.apache.jackrabbit.oak.spi.QueryIndex;
@@ -36,6 +37,7 @@ public class QueryEngineImpl implements
static final String SQL2 = "JCR-SQL2";
private static final String XPATH = "xpath";
+ private static final String JQOM = "JCR-JQOM";
private final MicroKernel mk;
private final CoreValueFactory vf;
@@ -51,7 +53,7 @@ public class QueryEngineImpl implements
@Override
public List<String> getSupportedQueryLanguages() {
- return Arrays.asList(SQL2, XPATH);
+ return Arrays.asList(SQL2, XPATH, JQOM);
}
/**
@@ -70,7 +72,7 @@ public class QueryEngineImpl implements
private Query parseQuery(String statement, String language) throws ParseException {
Query q;
- if (SQL2.equals(language)) {
+ if (SQL2.equals(language) || JQOM.equals(language)) {
q = parserSQL2.parse(statement);
} else if (XPATH.equals(language)) {
XPathToSQL2Converter converter = new XPathToSQL2Converter();
@@ -84,9 +86,11 @@ public class QueryEngineImpl implements
@Override
public ResultImpl executeQuery(String statement, String language, ContentSession session,
- long limit, long offset, Map<String, CoreValue> bindings) throws ParseException {
+ long limit, long offset, Map<String, CoreValue> bindings,
+ NamePathMapper namePathMapper) throws ParseException {
Query q = parseQuery(statement, language);
q.setSession(session);
+ q.setNamePathMapper(namePathMapper);
q.setLimit(limit);
q.setOffset(offset);
q.setMicroKernel(mk);
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/XPathToSQL2Converter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/XPathToSQL2Converter.java?rev=1344752&r1=1344751&r2=1344752&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/XPathToSQL2Converter.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/XPathToSQL2Converter.java Thu May 31 14:43:30 2012
@@ -169,8 +169,8 @@ public class XPathToSQL2Converter {
f.params.add(Literal.newString(path));
condition = add(condition, f);
} else {
- // TODO jcr:path is only a pseudo-property
- Condition c = new Condition(new Property("jcr:path"), "=", Literal.newString(path));
+ Function c = new Function("issamenode");
+ c.params.add(Literal.newString(path));
condition = add(condition, c);
}
if (nodeName != null) {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElement.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElement.java?rev=1344752&r1=1344751&r2=1344752&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElement.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElement.java Thu May 31 14:43:30 2012
@@ -24,6 +24,7 @@ import org.apache.jackrabbit.oak.api.Cor
import org.apache.jackrabbit.oak.api.CoreValueFactory;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.kernel.CoreValueMapper;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.query.Query;
import javax.jcr.PropertyType;
@@ -125,5 +126,18 @@ abstract class AstElement {
return true;
}
+ protected String getOakPath(String jcrPath) {
+ NamePathMapper m = query.getNamePathMapper();
+ if (m == null) {
+ // to simplify testing, a getNamePathMapper isn't required
+ return jcrPath;
+ }
+ String p = m.getOakPath(jcrPath);
+ if (p == null) {
+ throw new IllegalArgumentException("Not a valid JCR path: " + jcrPath);
+ }
+ return p;
+ }
+
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ComparisonImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ComparisonImpl.java?rev=1344752&r1=1344751&r2=1344752&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ComparisonImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/ComparisonImpl.java Thu May 31 14:43:30 2012
@@ -64,7 +64,7 @@ public class ComparisonImpl extends Cons
if (v1.getType() != v2.getType()) {
// "the value of operand2 is converted to the
// property type of the value of operand1"
- v2 = convert(query.getValueFactory(), v2, v1.getType());
+ v2 = convert(v2, v1.getType());
}
switch (operator) {
case EQUAL:
@@ -85,7 +85,7 @@ public class ComparisonImpl extends Cons
throw new IllegalArgumentException("Unknown operator: " + operator);
}
- private static CoreValue convert(CoreValueFactory vf, CoreValue v, int targetType) {
+ private CoreValue convert(CoreValue v, int targetType) {
// TODO support full set of conversion features defined in the JCR spec
// at 3.6.4 Property Type Conversion
// re-use existing code if possible
@@ -93,6 +93,7 @@ public class ComparisonImpl extends Cons
if (sourceType == targetType) {
return v;
}
+ CoreValueFactory vf = query.getValueFactory();
switch (sourceType) {
case PropertyType.STRING:
switch(targetType) {
@@ -122,7 +123,7 @@ public class ComparisonImpl extends Cons
case PropertyType.DECIMAL:
return vf.createValue(v.getString(), PropertyType.DECIMAL);
case PropertyType.NAME:
- return vf.createValue(v.getString(), PropertyType.NAME);
+ return vf.createValue(getOakPath(v.getString()), PropertyType.NAME);
case PropertyType.PATH:
return vf.createValue(v.getString(), PropertyType.PATH);
case PropertyType.REFERENCE:
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NodeNameImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NodeNameImpl.java?rev=1344752&r1=1344751&r2=1344752&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NodeNameImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/NodeNameImpl.java Thu May 31 14:43:30 2012
@@ -18,6 +18,7 @@
*/
package org.apache.jackrabbit.oak.query.ast;
+import javax.jcr.PropertyType;
import org.apache.jackrabbit.oak.api.CoreValue;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
@@ -55,7 +56,11 @@ public class NodeNameImpl extends Dynami
@Override
public CoreValue currentValue() {
String name = PathUtils.getName(selector.currentPath());
- return query.getValueFactory().createValue(name);
+ CoreValue v = query.getValueFactory().createValue(name);
+ String path = v.getString();
+ // normalize paths (./name > name)
+ path = getOakPath(path);
+ return query.getValueFactory().createValue(path, PropertyType.NAME);
}
@Override
@@ -64,10 +69,11 @@ public class NodeNameImpl extends Dynami
throw new IllegalArgumentException("Invalid name value: " + v.toString());
}
String path = v.getString();
+ // normalize paths (./name > name)
+ path = getOakPath(path);
if (PathUtils.isAbsolute(path)) {
throw new IllegalArgumentException("NAME() comparison with absolute path are not allowed: " + path);
}
- // TODO normalize paths (./name > name)
if (PathUtils.getDepth(path) > 1) {
throw new IllegalArgumentException("NAME() comparison with relative path are not allowed: " + path);
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeImpl.java?rev=1344752&r1=1344751&r2=1344752&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SameNodeImpl.java Thu May 31 14:43:30 2012
@@ -43,6 +43,7 @@ public class SameNodeImpl extends Constr
@Override
public boolean evaluate() {
String p = getAbsolutePath(path);
+ // TODO normalize paths
return selector.currentPath().equals(p);
}
@@ -69,6 +70,7 @@ public class SameNodeImpl extends Constr
String p = getAbsolutePath(path);
f.restrictPath(p, Filter.PathRestriction.EXACT);
}
+ // TODO validate absolute path
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/QueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/QueryTest.java?rev=1344752&r1=1344751&r2=1344752&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/QueryTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/QueryTest.java Thu May 31 14:43:30 2012
@@ -191,7 +191,7 @@ public class QueryTest extends AbstractQ
}
private Result executeQuery(String statement, HashMap<String, CoreValue> sv) throws ParseException {
- return qe.executeQuery(statement, QueryEngineImpl.SQL2, session, Long.MAX_VALUE, 0, sv);
+ return qe.executeQuery(statement, QueryEngineImpl.SQL2, session, Long.MAX_VALUE, 0, sv, null);
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/queryXpathTest.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/queryXpathTest.txt?rev=1344752&r1=1344751&r2=1344752&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/queryXpathTest.txt (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/queryXpathTest.txt Thu May 31 14:43:30 2012
@@ -19,7 +19,7 @@
# * use ascii character only
xpath /jcr:root/testdata/node[@jcr:primaryType]
-select [jcr:path], [jcr:score], * from [nt:base] where ([jcr:primaryType] is not null) and ([jcr:path] = '/testdata/node')
+select [jcr:path], [jcr:score], * from [nt:base] where ([jcr:primaryType] is not null) and issamenode('/testdata/node')
xpath //testroot/*[@jcr:primaryType='nt:unstructured'] order by @prop2, @prop1
invalid: Query: //testroot/*(*)[@jcr:primaryType='nt:unstructured'] order by @prop2, @prop1; expected: non-path condition
@@ -31,10 +31,10 @@ xpath /jcr:root/test//text()
select [jcr:path], [jcr:score], * from [nt:base] where isdescendantnode('/test') and (name() = 'jcr:xmltext')
xpath /jcr:root/test/jcr:xmltext
-select [jcr:path], [jcr:score], * from [nt:base] where [jcr:path] = '/test/jcr:xmltext'
+select [jcr:path], [jcr:score], * from [nt:base] where issamenode('/test/jcr:xmltext')
xpath /jcr:root/test/text()
-select [jcr:path], [jcr:score], * from [nt:base] where [jcr:path] = '/test/jcr:xmltext'
+select [jcr:path], [jcr:score], * from [nt:base] where issamenode('/test/jcr:xmltext')
xpath //*[@*='x']
select [jcr:path], [jcr:score], * from [nt:base] where [*] = 'x'
@@ -87,6 +87,9 @@ select [jcr:path], [jcr:score], * from [
xpath /jcr:root/content/campaigns//element(*, PageContent)[(@sling:resourceType = 'teaser' or @sling:resourceType = 'newsletter' or @teaserPageType = 'newsletter' or @teaserPageType = 'tweet') and ((@onTime < xs:dateTime('2012-04-01T00:00:00.000+02:00')) or not(@onTime)) and ((@offTime >= xs:dateTime('2012-02-26T00:00:00.000+01:00')) or not(@offTime))] order by @onTime
select [jcr:path], [jcr:score], * from [PageContent] where (((((([sling:resourceType] = 'teaser') or ([sling:resourceType] = 'newsletter')) or ([teaserPageType] = 'newsletter')) or ([teaserPageType] = 'tweet')) and (([onTime] < cast('2012-04-01T00:00:00.000+02:00' as date)) or ([onTime] is null))) and (([offTime] >= cast('2012-02-26T00:00:00.000+01:00' as date)) or ([offTime] is null))) and isdescendantnode('/content/campaigns') order by [onTime]
+xpath /jcr:root/content/dam//element(*, asset)
+select [jcr:path], [jcr:score], * from [asset] where isdescendantnode('/content/dam')
+
xpath /jcr:root/content/dam//element(*, asset)[jcr:content/metadata/@dam:scene]
select [jcr:path], [jcr:score], * from [asset] where ([jcr:content/metadata/dam:scene] is not null) and isdescendantnode('/content/dam')
@@ -129,7 +132,7 @@ xpath /jcr:root/nodes//element(*, my:typ
select [jcr:path], [jcr:score], * from [my:type] where isdescendantnode('/nodes')
xpath /jcr:root/some/element(nodes, my:type)
-select [jcr:path], [jcr:score], * from [my:type] where [jcr:path] = '/some/nodes'
+select [jcr:path], [jcr:score], * from [my:type] where issamenode('/some/nodes')
xpath /jcr:root/some/nodes/element(*, my:type)
select [jcr:path], [jcr:score], * from [my:type] where ischildnode('/some/nodes')