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/22 16:58:08 UTC
svn commit: r1341505 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/api/
oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/
oak-core/src/main/java/org/apache/jackrabbit/oak/query/
oak-core/src/main/java/org/apache/ja...
Author: thomasm
Date: Tue May 22 14:58:07 2012
New Revision: 1341505
URL: http://svn.apache.org/viewvc?rev=1341505&view=rev
Log:
OAK-28 Query implementation - implement missing features
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/kernel/CoreValueImpl.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/test/java/org/apache/jackrabbit/oak/query/QueryTest.java
jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/queryTest.txt
jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/queryXpathTest.txt
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryImpl.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryManagerImpl.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryResultImpl.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/RowImpl.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/qom/QueryObjectModelImpl.java
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=1341505&r1=1341504&r2=1341505&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 Tue May 22 14:58:07 2012
@@ -50,12 +50,15 @@ public interface QueryEngine {
* @param statement the query statement
* @param language the language
* @param session the content session to use
+ * @param limit the maximum result set size
+ * @param offset the number of rows to skip
* @param bindings the bind variable value bindings
* @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, Map<String, CoreValue> bindings) throws ParseException;
+ Result executeQuery(String statement, String language, ContentSession session,
+ long limit, long offset, Map<String, CoreValue> bindings) 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/kernel/CoreValueImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/CoreValueImpl.java?rev=1341505&r1=1341504&r2=1341505&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/CoreValueImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/CoreValueImpl.java Tue May 22 14:58:07 2012
@@ -17,12 +17,14 @@
package org.apache.jackrabbit.oak.kernel;
import org.apache.jackrabbit.oak.api.CoreValue;
+import org.apache.jackrabbit.util.ISO8601;
import javax.jcr.PropertyType;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
+import java.util.Calendar;
/**
* {@code CoreValueImpl} is the default implementation of the {@code CoreValue}
@@ -304,6 +306,10 @@ class CoreValueImpl implements CoreValue
return ((BigDecimal) value).compareTo(o.getDecimal());
case PropertyType.BOOLEAN:
return ((Boolean) value).compareTo(o.getBoolean());
+ case PropertyType.DATE:
+ Calendar d1 = ISO8601.parse(getString());
+ Calendar d2 = ISO8601.parse(o.getString());
+ return d1.compareTo(d2);
default:
return value.toString().compareTo(o.toString());
}
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=1341505&r1=1341504&r2=1341505&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 Tue May 22 14:58:07 2012
@@ -60,6 +60,7 @@ public class Query {
final SourceImpl source;
final ConstraintImpl constraint;
final HashMap<String, CoreValue> bindVariableMap = new HashMap<String, CoreValue>();
+ final HashMap<String, Integer> selectorIndexes = new HashMap<String, Integer>();
final ArrayList<SelectorImpl> selectors = new ArrayList<SelectorImpl>();
private MicroKernel mk;
@@ -67,7 +68,7 @@ public class Query {
private final OrderingImpl[] orderings;
private ColumnImpl[] columns;
private boolean explain;
- private long limit;
+ private long limit = Long.MAX_VALUE;
private long offset;
private boolean prepared;
private final CoreValueFactory valueFactory;
@@ -200,6 +201,10 @@ public class Query {
@Override
public boolean visit(SelectorImpl node) {
+ String name = node.getSelectorName();
+ if (selectorIndexes.put(name, selectors.size()) != null) {
+ throw new IllegalArgumentException("Two selectors with the same name: " + name);
+ }
selectors.add(node);
node.setQuery(query);
return true;
@@ -290,7 +295,7 @@ public class Query {
ResultRowImpl r = new ResultRowImpl(this, new String[0], new CoreValue[] { getValueFactory().createValue(plan) }, null);
it = Arrays.asList(r).iterator();
} else {
- it = new RowIterator(revisionId);
+ it = new RowIterator(revisionId, limit, offset);
if (orderings != null) {
// TODO "order by" is not necessary if the used index returns
// rows in the same order
@@ -345,15 +350,22 @@ public class Query {
private final String revisionId;
private ResultRowImpl current;
private boolean started, end;
+ private long limit, offset, rowIndex;
- RowIterator(String revisionId) {
+ RowIterator(String revisionId, long limit, long offset) {
this.revisionId = revisionId;
+ this.limit = limit;
+ this.offset = offset;
}
private void fetchNext() {
if (end) {
return;
}
+ if (rowIndex >= limit) {
+ end = true;
+ return;
+ }
if (!started) {
source.execute(revisionId);
started = true;
@@ -361,7 +373,12 @@ public class Query {
while (true) {
if (source.next()) {
if (constraint == null || constraint.evaluate()) {
+ if (offset > 0) {
+ offset--;
+ continue;
+ }
current = currentRow();
+ rowIndex++;
break;
}
} else {
@@ -430,12 +447,11 @@ public class Query {
}
public int getSelectorIndex(String selectorName) {
- for (int i = 0, size = selectors.size(); i < size; i++) {
- if (selectors.get(i).getSelectorName().equals(selectorName)) {
- return i;
- }
+ Integer index = selectorIndexes.get(selectorName);
+ if (index == null) {
+ throw new IllegalArgumentException("Unknown selector: " + selectorName);
}
- throw new IllegalArgumentException("Unknown selector: " + selectorName);
+ return index;
}
public int getColumnIndex(String columnName) {
@@ -448,14 +464,6 @@ public class Query {
throw new IllegalArgumentException("Column not found: " + columnName);
}
- public long getLimit() {
- return limit;
- }
-
- public long getOffset() {
- return offset;
- }
-
public CoreValue getBindVariableValue(String bindVariableName) {
CoreValue v = bindVariableMap.get(bindVariableName);
if (v == null) {
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=1341505&r1=1341504&r2=1341505&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 Tue May 22 14:58:07 2012
@@ -83,9 +83,12 @@ public class QueryEngineImpl implements
}
@Override
- public ResultImpl executeQuery(String statement, String language, ContentSession session, Map<String, CoreValue> bindings) throws ParseException {
+ public ResultImpl executeQuery(String statement, String language, ContentSession session,
+ long limit, long offset, Map<String, CoreValue> bindings) throws ParseException {
Query q = parseQuery(statement, language);
q.setSession(session);
+ q.setLimit(limit);
+ q.setOffset(offset);
q.setMicroKernel(mk);
if (bindings != null) {
for (Entry<String, CoreValue> e : bindings.entrySet()) {
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=1341505&r1=1341504&r2=1341505&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 Tue May 22 14:58:07 2012
@@ -64,14 +64,18 @@ public class XPathToSQL2Converter {
expected = new ArrayList<String>();
read();
String path = "";
+ String nodeName = null;
Expression condition = null;
String from = "nt:base";
ArrayList<Expression> columnList = new ArrayList<Expression>();
- boolean children = true;
- boolean descendants = true;
+ boolean children = false;
+ boolean descendants = false;
while (true) {
String nodeType;
if (readIf("/")) {
+ if (nodeName != null) {
+ throw getSyntaxError("non-path condition");
+ }
if (readIf("/")) {
descendants = true;
} else if (readIf("jcr:root")) {
@@ -81,6 +85,7 @@ public class XPathToSQL2Converter {
descendants = true;
}
} else {
+ descendants = true;
// expected end of statement
break;
}
@@ -90,11 +95,15 @@ public class XPathToSQL2Converter {
if (readIf("*")) {
nodeType = "nt:base";
from = nodeType;
+ children = true;
} else if (readIf("text")) {
- // TODO support text() and jcr:xmltext?
read("(");
read(")");
- path = PathUtils.concat(path, "jcr:xmltext");
+ if (descendants) {
+ nodeName = "jcr:xmltext";
+ } else {
+ path = PathUtils.concat(path, "jcr:xmltext");
+ }
} else if (readIf("element")) {
read("(");
if (readIf(")")) {
@@ -119,19 +128,22 @@ public class XPathToSQL2Converter {
read(")");
}
} else if (readIf("@")) {
- Property p = new Property(readIdentifier());
+ Property p = readProperty();
columnList.add(p);
} else if (readIf("(")) {
do {
read("@");
- Property p = new Property(readIdentifier());
+ Property p = readProperty();
columnList.add(p);
} while (readIf("|"));
read(")");
} else {
- String name = readIdentifier();
- path = PathUtils.concat(path, name);
- continue;
+ if (descendants) {
+ nodeName = readIdentifier();
+ } else {
+ String name = readIdentifier();
+ path = PathUtils.concat(path, name);
+ }
}
if (readIf("[")) {
Expression c = parseConstraint();
@@ -145,6 +157,9 @@ public class XPathToSQL2Converter {
if (path.isEmpty()) {
// no condition
} else {
+ if (!PathUtils.isAbsolute(path)) {
+ path = PathUtils.concat("/", path);
+ }
if (descendants) {
Function c = new Function("isdescendantnode");
c.params.add(Literal.newString(path));
@@ -158,6 +173,11 @@ public class XPathToSQL2Converter {
Condition c = new Condition(new Property("jcr:path"), "=", Literal.newString(path));
condition = add(condition, c);
}
+ if (nodeName != null) {
+ Function f = new Function("name");
+ Condition c = new Condition(f, "=", Literal.newString(nodeName));
+ condition = add(condition, c);
+ }
}
ArrayList<Order> orderList = new ArrayList<Order>();
if (readIf("order")) {
@@ -177,7 +197,7 @@ public class XPathToSQL2Converter {
throw getSyntaxError("<end>");
}
StringBuilder buff = new StringBuilder("select ");
- buff.append("[jcr:path], ");
+ buff.append("[jcr:path], [jcr:score], ");
if (columnList.isEmpty()) {
buff.append('*');
} else {
@@ -279,7 +299,7 @@ public class XPathToSQL2Converter {
private Expression parseExpression() throws ParseException {
if (readIf("@")) {
- return new Property(readIdentifier());
+ return readProperty();
} else if (readIf("true")) {
return Literal.newBoolean(true);
} else if (readIf("false")) {
@@ -384,6 +404,13 @@ public class XPathToSQL2Converter {
read();
}
+ private Property readProperty() throws ParseException {
+ if (readIf("*")) {
+ return new Property("*");
+ }
+ return new Property(readIdentifier());
+ }
+
private String readIdentifier() throws ParseException {
if (currentTokenType != IDENTIFIER) {
throw getSyntaxError("identifier");
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=1341505&r1=1341504&r2=1341505&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 Tue May 22 14:58:07 2012
@@ -18,6 +18,7 @@
*/
package org.apache.jackrabbit.oak.query.ast;
+import javax.jcr.PropertyType;
import org.apache.jackrabbit.mk.json.JsopReader;
import org.apache.jackrabbit.mk.json.JsopTokenizer;
import org.apache.jackrabbit.oak.api.CoreValue;
@@ -100,5 +101,28 @@ abstract class AstElement {
return CoreValueMapper.fromJsopReader(r, vf);
}
+ /**
+ * Validate that the givne value can be converted to a JCR name.
+ *
+ * @param v the value
+ * @return true if it can be converted
+ */
+ protected boolean isName(CoreValue v) {
+ // TODO correctly validate JCR names - see JCR 2.0 spec 3.2.4 Naming Restrictions
+ switch (v.getType()) {
+ case PropertyType.DATE:
+ case PropertyType.DECIMAL:
+ case PropertyType.DOUBLE:
+ case PropertyType.LONG:
+ case PropertyType.BOOLEAN:
+ return false;
+ }
+ String n = v.getString();
+ if (n.startsWith("[") && !n.endsWith("]")) {
+ return false;
+ }
+ return true;
+ }
+
}
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=1341505&r1=1341504&r2=1341505&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 Tue May 22 14:58:07 2012
@@ -105,9 +105,12 @@ public class ComparisonImpl extends Cons
// except if UTF-8 isn't supported
throw new IllegalArgumentException(v.getString(), e);
}
- case PropertyType.DATE:
-
}
+ return vf.createValue(v.getString(), targetType);
+ }
+ switch (targetType) {
+ case PropertyType.STRING:
+ return vf.createValue(v.getString());
case PropertyType.BOOLEAN:
return vf.createValue(v.getBoolean());
case PropertyType.DATE:
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=1341505&r1=1341504&r2=1341505&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 Tue May 22 14:58:07 2012
@@ -18,8 +18,8 @@
*/
package org.apache.jackrabbit.oak.query.ast;
-import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.api.CoreValue;
+import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
public class NodeNameImpl extends DynamicOperandImpl {
@@ -60,6 +60,17 @@ public class NodeNameImpl extends Dynami
@Override
public void apply(FilterImpl f, Operator operator, CoreValue v) {
+ if (!isName(v)) {
+ throw new IllegalArgumentException("Invalid name value: " + v.toString());
+ }
+ String path = v.getString();
+ 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);
+ }
// TODO support NAME(..) index conditions
}
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=1341505&r1=1341504&r2=1341505&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 Tue May 22 14:58:07 2012
@@ -159,14 +159,20 @@ public class QueryTest extends AbstractQ
}
}
- private List<String> executeQuery(String query) throws ParseException {
+ private List<String> executeQuery(String query) {
List<String> lines = new ArrayList<String>();
- Result result = executeQuery(query, null);
- for (ResultRow row : result.getRows()) {
- lines.add(readRow(row));
- }
- if (!query.contains("order by")) {
- Collections.sort(lines);
+ try {
+ Result result = executeQuery(query, null);
+ for (ResultRow row : result.getRows()) {
+ lines.add(readRow(row));
+ }
+ if (!query.contains("order by")) {
+ Collections.sort(lines);
+ }
+ } catch (ParseException e) {
+ lines.add(e.toString());
+ } catch (IllegalArgumentException e) {
+ lines.add(e.toString());
}
return lines;
}
@@ -185,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, sv);
+ return qe.executeQuery(statement, QueryEngineImpl.SQL2, session, Long.MAX_VALUE, 0, sv);
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/queryTest.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/queryTest.txt?rev=1341505&r1=1341504&r2=1341505&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/queryTest.txt (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/resources/org/apache/jackrabbit/oak/query/queryTest.txt Tue May 22 14:58:07 2012
@@ -23,6 +23,9 @@
# test the property content index
+select * from [nt:base] as p inner join [nt:base] as p on ischildnode(p, p) where p.[jcr:path] = '/'
+java.lang.IllegalArgumentException: Two selectors with the same name: p
+
commit /default + "test": { "a": { "id": "10" }, "b": { "id" : "20" }}
commit /jcr:system/indexes + "property:id": {}
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=1341505&r1=1341504&r2=1341505&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 Tue May 22 14:58:07 2012
@@ -18,160 +18,175 @@
# * lines starting with "xpath" are xpath queries, followed by expected sql2 query
# * use ascii character only
-xpath /jcr:root
-select [jcr:path], * from [nt:base] where isdescendantnode('/')
+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')
-xpath /jcr:root/test/text()
-select [jcr:path], * from [nt:base] where ischildnode('/test/jcr:xmltext')
+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
+
+xpath /jcr:root/test//jcr:xmltext
+select [jcr:path], [jcr:score], * from [nt:base] where isdescendantnode('/test') and (name() = 'jcr:xmltext')
+
+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], * from [nt:base] where ischildnode('/test/jcr:xmltext')
+select [jcr:path], [jcr:score], * from [nt:base] where [jcr:path] = '/test/jcr:xmltext'
+
+xpath /jcr:root/test/text()
+select [jcr:path], [jcr:score], * from [nt:base] where [jcr:path] = '/test/jcr:xmltext'
+
+xpath //*[@*='x']
+select [jcr:path], [jcr:score], * from [nt:base] where [*] = 'x'
+
+xpath /jcr:root
+select [jcr:path], [jcr:score], * from [nt:base] where isdescendantnode('/')
xpath //*[@name='Hello']
-select [jcr:path], * from [nt:base] where [name] = 'Hello'
+select [jcr:path], [jcr:score], * from [nt:base] where [name] = 'Hello'
xpath /jcr:root//*[@name='Hello']
-select [jcr:path], * from [nt:base] where ([name] = 'Hello') and isdescendantnode('/')
+select [jcr:path], [jcr:score], * from [nt:base] where ([name] = 'Hello') and isdescendantnode('/')
xpath content/*
-select [jcr:path], * from [nt:base] where ischildnode('/content')
+select [jcr:path], [jcr:score], * from [nt:base] where ischildnode('/content')
xpath content//*
-select [jcr:path], * from [nt:base] where isdescendantnode('/content')
+select [jcr:path], [jcr:score], * from [nt:base] where isdescendantnode('/content')
xpath content//*[@name='Hello']
-select [jcr:path], * from [nt:base] where ([name] = 'Hello') and isdescendantnode('/content')
+select [jcr:path], [jcr:score], * from [nt:base] where ([name] = 'Hello') and isdescendantnode('/content')
xpath /jcr:root/content//*[@name='Hello']
-select [jcr:path], * from [nt:base] where ([name] = 'Hello') and isdescendantnode('/content')
+select [jcr:path], [jcr:score], * from [nt:base] where ([name] = 'Hello') and isdescendantnode('/content')
xpath //*[jcr:contains(., 'test')] order by @jcr:score
-select [jcr:path], * from [nt:base] where contains(*, 'test') order by [jcr:score]
+select [jcr:path], [jcr:score], * from [nt:base] where contains(*, 'test') order by [jcr:score]
xpath /jcr:root//*[jcr:contains(., 'test')] order by @jcr:score
-select [jcr:path], * from [nt:base] where contains(*, 'test') and isdescendantnode('/') order by [jcr:score]
+select [jcr:path], [jcr:score], * from [nt:base] where contains(*, 'test') and isdescendantnode('/') order by [jcr:score]
xpath /jcr:root//element(*, test)
-select [jcr:path], * from [test] where isdescendantnode('/')
+select [jcr:path], [jcr:score], * from [test] where isdescendantnode('/')
xpath /jcr:root//element(*, user)[test/@jcr:primaryType]
-select [jcr:path], * from [user] where ([test/jcr:primaryType] is not null) and isdescendantnode('/')
+select [jcr:path], [jcr:score], * from [user] where ([test/jcr:primaryType] is not null) and isdescendantnode('/')
xpath /jcr:root/content//*[(@sling:resourceType = 'start')]
-select [jcr:path], * from [nt:base] where ([sling:resourceType] = 'start') and isdescendantnode('/content')
+select [jcr:path], [jcr:score], * from [nt:base] where ([sling:resourceType] = 'start') and isdescendantnode('/content')
xpath /jcr:root/content//*[(@sling:resourceType = 'page')]
-select [jcr:path], * from [nt:base] where ([sling:resourceType] = 'page') and isdescendantnode('/content')
+select [jcr:path], [jcr:score], * from [nt:base] where ([sling:resourceType] = 'page') and isdescendantnode('/content')
xpath /jcr:root/content//*[@offTime > xs:dateTime('2012-03-28T15:56:18.327+02:00') or @onTime > xs:dateTime('2012-03-28T15:56:18.327+02:00')]
-select [jcr:path], * from [nt:base] where (([offTime] > cast('2012-03-28T15:56:18.327+02:00' as date)) or ([onTime] > cast('2012-03-28T15:56:18.327+02:00' as date))) and isdescendantnode('/content')
+select [jcr:path], [jcr:score], * from [nt:base] where (([offTime] > cast('2012-03-28T15:56:18.327+02:00' as date)) or ([onTime] > cast('2012-03-28T15:56:18.327+02:00' as date))) and isdescendantnode('/content')
xpath /jcr:root/content/campaigns//*[@jcr:primaryType='Page'] order by jcr:content/@lastModified descending
-select [jcr:path], * from [nt:base] where ([jcr:primaryType] = 'Page') and isdescendantnode('/content/campaigns') order by [jcr:content/lastModified] desc
+select [jcr:path], [jcr:score], * from [nt:base] where ([jcr:primaryType] = 'Page') and isdescendantnode('/content/campaigns') order by [jcr:content/lastModified] desc
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], * 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]
+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)[jcr:content/metadata/@dam:scene]
-select [jcr:path], * from [asset] where ([jcr:content/metadata/dam:scene] is not null) and isdescendantnode('/content/dam')
+select [jcr:path], [jcr:score], * from [asset] where ([jcr:content/metadata/dam:scene] is not null) and isdescendantnode('/content/dam')
xpath /jcr:root/etc/cloud//*[(@sling:resourceType = 'framework')]
-select [jcr:path], * from [nt:base] where ([sling:resourceType] = 'framework') and isdescendantnode('/etc/cloud')
+select [jcr:path], [jcr:score], * from [nt:base] where ([sling:resourceType] = 'framework') and isdescendantnode('/etc/cloud')
xpath /jcr:root/etc/cloud//*[(@sling:resourceType = 'analytics')]
-select [jcr:path], * from [nt:base] where ([sling:resourceType] = 'analytics') and isdescendantnode('/etc/cloud')
+select [jcr:path], [jcr:score], * from [nt:base] where ([sling:resourceType] = 'analytics') and isdescendantnode('/etc/cloud')
xpath /jcr:root/etc/reports//*[@jcr:primaryType='Page'] order by jcr:content/@lastModified descending
-select [jcr:path], * from [nt:base] where ([jcr:primaryType] = 'Page') and isdescendantnode('/etc/reports') order by [jcr:content/lastModified] desc
+select [jcr:path], [jcr:score], * from [nt:base] where ([jcr:primaryType] = 'Page') and isdescendantnode('/etc/reports') order by [jcr:content/lastModified] desc
xpath /jcr:root/etc/segment//*[@jcr:primaryType='Page'] order by jcr:content/@lastModified descending
-select [jcr:path], * from [nt:base] where ([jcr:primaryType] = 'Page') and isdescendantnode('/etc/segment') order by [jcr:content/lastModified] desc
+select [jcr:path], [jcr:score], * from [nt:base] where ([jcr:primaryType] = 'Page') and isdescendantnode('/etc/segment') order by [jcr:content/lastModified] desc
xpath /jcr:root/etc/workflow//element(*,Item)[not(meta/@archived) and not(meta/@archived = true)]
-select [jcr:path], * from [Item] where (([meta/archived] is null) and not([meta/archived] = true)) and isdescendantnode('/etc/workflow')
+select [jcr:path], [jcr:score], * from [Item] where (([meta/archived] is null) and not([meta/archived] = true)) and isdescendantnode('/etc/workflow')
xpath /jcr:root/home//element()
-select [jcr:path], * from [nt:base] where isdescendantnode('/home')
+select [jcr:path], [jcr:score], * from [nt:base] where isdescendantnode('/home')
xpath /jcr:root/home//element(*)
-select [jcr:path], * from [nt:base] where isdescendantnode('/home')
+select [jcr:path], [jcr:score], * from [nt:base] where isdescendantnode('/home')
# other queries
xpath //*
-select [jcr:path], * from [nt:base]
+select [jcr:path], [jcr:score], * from [nt:base]
xpath //element(*, my:type)
-select [jcr:path], * from [my:type]
+select [jcr:path], [jcr:score], * from [my:type]
xpath //element(*, my:type)/@my:title
-select [jcr:path], [my:title] from [my:type]
+select [jcr:path], [jcr:score], [my:title] from [my:type]
xpath //element(*, my:type)/(@my:title | @my:text)
-select [jcr:path], [my:title], [my:text] from [my:type]
+select [jcr:path], [jcr:score], [my:title], [my:text] from [my:type]
xpath /jcr:root/nodes//element(*, my:type)
-select [jcr:path], * from [my:type] where isdescendantnode('/nodes')
+select [jcr:path], [jcr:score], * from [my:type] where isdescendantnode('/nodes')
xpath /jcr:root/some/element(nodes, my:type)
-select [jcr:path], * from [my:type] where [jcr:path] = '/some/nodes'
+select [jcr:path], [jcr:score], * from [my:type] where [jcr:path] = '/some/nodes'
xpath /jcr:root/some/nodes/element(*, my:type)
-select [jcr:path], * from [my:type] where ischildnode('/some/nodes')
+select [jcr:path], [jcr:score], * from [my:type] where ischildnode('/some/nodes')
xpath /jcr:root/some/nodes//element(*, my:type)
-select [jcr:path], * from [my:type] where isdescendantnode('/some/nodes')
+select [jcr:path], [jcr:score], * from [my:type] where isdescendantnode('/some/nodes')
xpath //element(*, my:type)[@my:title = 'JSR 170']
-select [jcr:path], * from [my:type] where [my:title] = 'JSR 170'
+select [jcr:path], [jcr:score], * from [my:type] where [my:title] = 'JSR 170'
xpath //element(*, my:type)[jcr:like(@title,'%Java%')]
-select [jcr:path], * from [my:type] where [title] like '%Java%'
+select [jcr:path], [jcr:score], * from [my:type] where [title] like '%Java%'
xpath //element(*, my:type)[jcr:contains(., 'JSR 170')]
-select [jcr:path], * from [my:type] where contains(*, 'JSR 170')
+select [jcr:path], [jcr:score], * from [my:type] where contains(*, 'JSR 170')
xpath //element(*, my:type)[@my:title]
-select [jcr:path], * from [my:type] where [my:title] is not null
+select [jcr:path], [jcr:score], * from [my:type] where [my:title] is not null
xpath //element(*, my:type)[not(@my:title)]
-select [jcr:path], * from [my:type] where [my:title] is null
+select [jcr:path], [jcr:score], * from [my:type] where [my:title] is null
xpath //element(*, my:type)[@my:value < -1.0]
-select [jcr:path], * from [my:type] where [my:value] < -1.0
+select [jcr:path], [jcr:score], * from [my:type] where [my:value] < -1.0
xpath //element(*, my:type)[@my:value > +10123123123]
-select [jcr:path], * from [my:type] where [my:value] > 10123123123
+select [jcr:path], [jcr:score], * from [my:type] where [my:value] > 10123123123
xpath //element(*, my:type)[@my:value <= 10.3e-3]
-select [jcr:path], * from [my:type] where [my:value] <= 10.3e-3
+select [jcr:path], [jcr:score], * from [my:type] where [my:value] <= 10.3e-3
xpath //element(*, my:type)[@my:value >= 0e3]
-select [jcr:path], * from [my:type] where [my:value] >= 0e3
+select [jcr:path], [jcr:score], * from [my:type] where [my:value] >= 0e3
xpath //element(*, my:type)[@my:value <> 'Joe''s Caffee']
-select [jcr:path], * from [my:type] where [my:value] <> 'Joe''s Caffee'
+select [jcr:path], [jcr:score], * from [my:type] where [my:value] <> 'Joe''s Caffee'
xpath //element(*, my:type)[(not(@my:title) and @my:subject)]
-select [jcr:path], * from [my:type] where ([my:title] is null) and ([my:subject] is not null)
+select [jcr:path], [jcr:score], * from [my:type] where ([my:title] is null) and ([my:subject] is not null)
xpath //element(*, my:type)[not(@my:title) or @my:subject]
-select [jcr:path], * from [my:type] where ([my:title] is null) or ([my:subject] is not null)
+select [jcr:path], [jcr:score], * from [my:type] where ([my:title] is null) or ([my:subject] is not null)
xpath //element(*, my:type)[not(@my:value > 0 and @my:value < 100)]
-select [jcr:path], * from [my:type] where not(([my:value] > 0) and ([my:value] < 100))
+select [jcr:path], [jcr:score], * from [my:type] where not(([my:value] > 0) and ([my:value] < 100))
xpath //element(*, my:type) order by @jcr:lastModified
-select [jcr:path], * from [my:type] order by [jcr:lastModified]
+select [jcr:path], [jcr:score], * from [my:type] order by [jcr:lastModified]
xpath //element(*, my:type) order by @my:date descending, @my:title ascending
-select [jcr:path], * from [my:type] order by [my:date] desc, [my:title]
+select [jcr:path], [jcr:score], * from [my:type] order by [my:date] desc, [my:title]
xpath //element(*, my:type)[jcr:contains(., 'jcr')] order by jcr:score() descending
-select [jcr:path], * from [my:type] where contains(*, 'jcr') order by score() desc
+select [jcr:path], [jcr:score], * from [my:type] where contains(*, 'jcr') order by score() desc
xpath //element(*, my:type)[jcr:contains(@my:title, 'jcr')] order by jcr:score() descending
-select [jcr:path], * from [my:type] where contains([my:title], 'jcr') order by score() desc
+select [jcr:path], [jcr:score], * from [my:type] where contains([my:title], 'jcr') order by score() desc
xpath [invalid/query
invalid: Query: /jcr:root/[(*)invalid/query; expected: identifier
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryImpl.java?rev=1341505&r1=1341504&r2=1341505&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryImpl.java Tue May 22 14:58:07 2012
@@ -20,14 +20,21 @@ package org.apache.jackrabbit.oak.jcr.qu
import java.util.HashMap;
import java.util.List;
+import javax.jcr.ItemExistsException;
+import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
-import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.Value;
+import javax.jcr.nodetype.NodeType;
import javax.jcr.query.InvalidQueryException;
import javax.jcr.query.Query;
import javax.jcr.query.QueryResult;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.jcr.NodeDelegate;
+import org.apache.jackrabbit.oak.jcr.NodeImpl;
+import org.apache.jackrabbit.oak.jcr.SessionDelegate;
+import org.apache.jackrabbit.oak.jcr.value.ValueFactoryImpl;
/**
* The implementation of the corresponding JCR interface.
@@ -38,8 +45,10 @@ public class QueryImpl implements Query
private final HashMap<String, Value> bindVariableMap = new HashMap<String, Value>();
private final String language;
private final String statement;
- private long limit, offset;
+ private long limit = Long.MAX_VALUE;
+ private long offset;
private boolean parsed;
+ private String storedQueryPath;
QueryImpl(QueryManagerImpl manager, String statement, String language) {
this.manager = manager;
@@ -47,6 +56,10 @@ public class QueryImpl implements Query
this.language = language;
}
+ void setStoredQueryPath(String storedQueryPath) {
+ this.storedQueryPath = storedQueryPath;
+ }
+
@Override
public void bindValue(String varName, Value value) throws RepositoryException {
parse();
@@ -64,11 +77,12 @@ public class QueryImpl implements Query
for (String n : names) {
bindVariableMap.put(n, null);
}
+ parsed = true;
}
@Override
public QueryResult execute() throws RepositoryException {
- return manager.executeQuery(statement, language, bindVariableMap, limit, offset);
+ return manager.executeQuery(statement, language, limit, offset, bindVariableMap);
}
@Override
@@ -91,8 +105,10 @@ public class QueryImpl implements Query
@Override
public String getStoredQueryPath() throws RepositoryException {
- // TODO not implemented yet
- return null;
+ if (storedQueryPath == null) {
+ throw new ItemNotFoundException("Not a stored query");
+ }
+ return storedQueryPath;
}
@Override
@@ -108,11 +124,26 @@ public class QueryImpl implements Query
@Override
public Node storeAsNode(String absPath) throws RepositoryException {
manager.ensureIsAlive();
- if (manager.getSessionDelegate().getNode(absPath) == null) {
- throw new PathNotFoundException("The specified path does not exist: " + absPath);
+ SessionDelegate sessionDelegate = manager.getSessionDelegate();
+ String oakPath = sessionDelegate.getOakPathOrThrow(absPath);
+ // TODO query nodes should be of type nt:query
+ String parent = PathUtils.getParentPath(oakPath);
+ String nodeName = PathUtils.getName(oakPath);
+ NodeDelegate parentNode = sessionDelegate.getNode(parent);
+ ValueFactoryImpl vf = sessionDelegate.getValueFactory();
+ if (parentNode == null) {
+ throw new PathNotFoundException("The specified path does not exist: " + parent);
+ }
+ NodeDelegate node = parentNode.addChild(nodeName);
+ if (node == null) {
+ throw new ItemExistsException("Node already exists: " + absPath);
}
- // TODO not implemented yet
- throw new UnsupportedRepositoryOperationException("This feature is not supported");
+ node.setProperty("statement", vf.getCoreValue(vf.createValue(statement)));
+ node.setProperty("language", vf.getCoreValue(vf.createValue(language)));
+ NodeImpl n = new NodeImpl(node);
+ n.setPrimaryType(NodeType.NT_QUERY);
+ storedQueryPath = oakPath;
+ return n;
}
}
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryManagerImpl.java?rev=1341505&r1=1341504&r2=1341505&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryManagerImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryManagerImpl.java Tue May 22 14:58:07 2012
@@ -27,6 +27,7 @@ import java.util.Map.Entry;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
+import javax.jcr.nodetype.NodeType;
import javax.jcr.query.InvalidQueryException;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
@@ -71,8 +72,14 @@ public class QueryManagerImpl implements
@Override
public Query getQuery(Node node) throws RepositoryException {
- // TODO getQuery(Node node): is it needed?
- throw new RepositoryException("Feature not implemented");
+ if (!node.isNodeType(NodeType.NT_QUERY)) {
+ throw new InvalidQueryException("Not an nt:query node: " + node.getPath());
+ }
+ String statement = node.getProperty("statement").getString();
+ String language = node.getProperty("language").getString();
+ QueryImpl query = createQuery(statement, language);
+ query.setStoredQueryPath(node.getPath());
+ return query;
}
@Override
@@ -94,11 +101,11 @@ public class QueryManagerImpl implements
}
public QueryResult executeQuery(String statement, String language,
- HashMap<String, Value> bindVariableMap, long limit, long offset) throws RepositoryException {
+ long limit, long offset, HashMap<String, Value> bindVariableMap) throws RepositoryException {
try {
HashMap<String, CoreValue> bindMap = convertMap(bindVariableMap);
ContentSession s = sessionDelegate.getContentSession();
- Result r = queryEngine.executeQuery(statement, language, s, bindMap);
+ Result r = queryEngine.executeQuery(statement, language, s, limit, offset, bindMap);
return new QueryResultImpl(sessionDelegate, r);
} catch (IllegalArgumentException e) {
throw new InvalidQueryException(e);
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryResultImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryResultImpl.java?rev=1341505&r1=1341504&r2=1341505&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryResultImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryResultImpl.java Tue May 22 14:58:07 2012
@@ -18,23 +18,23 @@
*/
package org.apache.jackrabbit.oak.jcr.query;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.query.QueryResult;
+import javax.jcr.query.RowIterator;
import org.apache.jackrabbit.commons.iterator.NodeIteratorAdapter;
import org.apache.jackrabbit.commons.iterator.RowIteratorAdapter;
+import org.apache.jackrabbit.oak.api.CoreValue;
import org.apache.jackrabbit.oak.api.Result;
import org.apache.jackrabbit.oak.api.ResultRow;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.jcr.NodeDelegate;
import org.apache.jackrabbit.oak.jcr.NodeImpl;
import org.apache.jackrabbit.oak.jcr.SessionDelegate;
-import org.apache.jackrabbit.oak.jcr.value.ValueFactoryImpl;
-
-import javax.jcr.NodeIterator;
-import javax.jcr.RepositoryException;
-import javax.jcr.query.QueryResult;
-import javax.jcr.query.RowIterator;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
/**
* The implementation of the corresponding JCR interface.
@@ -42,14 +42,12 @@ import java.util.NoSuchElementException;
public class QueryResultImpl implements QueryResult {
final SessionDelegate sessionDelegate;
- final ValueFactoryImpl valueFactory;
final Result result;
final String pathFilter;
public QueryResultImpl(SessionDelegate sessionDelegate, Result result) {
this.sessionDelegate = sessionDelegate;
this.result = result;
- this.valueFactory = sessionDelegate.getValueFactory();
// TODO the path currently contains the workspace name
// TODO filter in oak-core once we support workspaces there
@@ -84,8 +82,8 @@ public class QueryResultImpl implements
for (String s : getSelectorNames()) {
String path = r.getPath(s);
if (PathUtils.isAncestor(pathFilter, path)) {
- current = new RowImpl(sessionDelegate, r, valueFactory);
- break;
+ current = new RowImpl(QueryResultImpl.this, r);
+ return;
}
}
}
@@ -115,10 +113,20 @@ public class QueryResultImpl implements
return new RowIteratorAdapter(it);
}
+ NodeImpl getNode(String path) {
+ NodeDelegate d = sessionDelegate.getNode(path);
+ return new NodeImpl(d);
+ }
+
+ String getLocalPath(String path) {
+ return PathUtils.concat("/", PathUtils.relativize(pathFilter, path));
+ }
+
@Override
public NodeIterator getNodes() throws RepositoryException {
if (getSelectorNames().length > 1) {
- throw new RepositoryException("Query contains more than one selector: " + Arrays.toString(getSelectorNames()));
+ throw new RepositoryException("Query contains more than one selector: " +
+ Arrays.toString(getSelectorNames()));
}
Iterator<NodeImpl> it = new Iterator<NodeImpl>() {
@@ -135,9 +143,7 @@ public class QueryResultImpl implements
ResultRow r = it.next();
String path = r.getPath();
if (PathUtils.isAncestor(pathFilter, path)) {
- path = PathUtils.relativize(pathFilter, path);
- NodeDelegate d = sessionDelegate.getNode(path);
- current = new NodeImpl(d);
+ current = getNode(getLocalPath(path));
break;
}
}
@@ -167,4 +173,8 @@ public class QueryResultImpl implements
return new NodeIteratorAdapter(it);
}
+ Value createValue(CoreValue value) {
+ return sessionDelegate.getValueFactory().createValue(value);
+ }
+
}
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/RowImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/RowImpl.java?rev=1341505&r1=1341504&r2=1341505&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/RowImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/RowImpl.java Tue May 22 14:58:07 2012
@@ -18,52 +18,40 @@
*/
package org.apache.jackrabbit.oak.jcr.query;
-import org.apache.jackrabbit.oak.api.CoreValue;
-import org.apache.jackrabbit.oak.api.ResultRow;
-import org.apache.jackrabbit.oak.jcr.NodeDelegate;
-import org.apache.jackrabbit.oak.jcr.NodeImpl;
-import org.apache.jackrabbit.oak.jcr.SessionDelegate;
-import org.apache.jackrabbit.oak.jcr.value.ValueFactoryImpl;
-
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.query.Row;
+import org.apache.jackrabbit.oak.api.CoreValue;
+import org.apache.jackrabbit.oak.api.ResultRow;
/**
* The implementation of the corresponding JCR interface.
*/
public class RowImpl implements Row {
- private final SessionDelegate sessionDelegate;
+ private final QueryResultImpl result;
private final ResultRow row;
- private final ValueFactoryImpl valueFactory;
- public RowImpl(SessionDelegate sessionDelegate, ResultRow row, ValueFactoryImpl valueFactory) {
- this.sessionDelegate = sessionDelegate;
+ public RowImpl(QueryResultImpl result, ResultRow row) {
+ this.result = result;
this.row = row;
- this.valueFactory = valueFactory;
}
@Override
public Node getNode() throws RepositoryException {
- return getNodeForPath(getPath());
+ return result.getNode(getPath());
}
@Override
public Node getNode(String selectorName) throws RepositoryException {
- return getNodeForPath(getPath(selectorName));
- }
-
- private Node getNodeForPath(String path) {
- NodeDelegate d = sessionDelegate.getNode(path);
- return new NodeImpl(d);
+ return result.getNode(getPath(selectorName));
}
@Override
public String getPath() throws RepositoryException {
try {
- return row.getPath();
+ return result.getLocalPath(row.getPath());
} catch (IllegalArgumentException e) {
throw new RepositoryException(e);
}
@@ -72,7 +60,7 @@ public class RowImpl implements Row {
@Override
public String getPath(String selectorName) throws RepositoryException {
try {
- return row.getPath(selectorName);
+ return result.getLocalPath(row.getPath(selectorName));
} catch (IllegalArgumentException e) {
throw new RepositoryException(e);
}
@@ -93,7 +81,7 @@ public class RowImpl implements Row {
@Override
public Value getValue(String columnName) throws RepositoryException {
try {
- return valueFactory.createValue(row.getValue(columnName));
+ return result.createValue(row.getValue(columnName));
} catch (IllegalArgumentException e) {
throw new RepositoryException(e);
}
@@ -105,7 +93,7 @@ public class RowImpl implements Row {
int len = values.length;
Value[] v2 = new Value[values.length];
for (int i = 0; i < len; i++) {
- v2[i] = valueFactory.createValue(values[i]);
+ v2[i] = result.createValue(values[i]);
}
return v2;
}
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/qom/QueryObjectModelImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/qom/QueryObjectModelImpl.java?rev=1341505&r1=1341504&r2=1341505&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/qom/QueryObjectModelImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/qom/QueryObjectModelImpl.java Tue May 22 14:58:07 2012
@@ -15,6 +15,7 @@ package org.apache.jackrabbit.oak.jcr.qu
import java.util.ArrayList;
import java.util.HashMap;
+import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
@@ -42,12 +43,14 @@ public class QueryObjectModelImpl implem
final ArrayList<Selector> selectors = new ArrayList<Selector>();
private final Ordering[] orderings;
private final Column[] columns;
- private long limit;
+ private long limit = Long.MAX_VALUE;
private long offset;
private boolean parsed;
+ private String storedQueryPath;
- public QueryObjectModelImpl(QueryManagerImpl queryManager, ValueFactory valueFactory, Source source, Constraint constraint, Ordering[] orderings,
- Column[] columns) {
+ public QueryObjectModelImpl(QueryManagerImpl queryManager,
+ ValueFactory valueFactory, Source source, Constraint constraint,
+ Ordering[] orderings, Column[] columns) {
this.queryManager = queryManager;
this.valueFactory = valueFactory;
this.source = source;
@@ -108,7 +111,8 @@ public class QueryObjectModelImpl implem
public void bindValue(String varName, Value value) throws RepositoryException {
parse();
if (!bindVariableMap.containsKey(varName)) {
- throw new IllegalArgumentException("Variable name " + varName + " is not a valid variable in this query");
+ throw new IllegalArgumentException("Variable name " + varName +
+ " is not a valid variable in this query");
}
bindVariableMap.put(varName, value);
}
@@ -117,15 +121,18 @@ public class QueryObjectModelImpl implem
if (parsed) {
return;
}
- String[] names = queryManager.createQuery(getStatement(), Query.JCR_SQL2).getBindVariableNames();
+ String[] names = queryManager.createQuery(getStatement(), Query.JCR_SQL2).
+ getBindVariableNames();
for (String n : names) {
bindVariableMap.put(n, null);
}
+ parsed = true;
}
@Override
public QueryResult execute() throws RepositoryException {
- return queryManager.executeQuery(getStatement(), Query.JCR_SQL2, bindVariableMap, limit, offset);
+ return queryManager.executeQuery(getStatement(), Query.JCR_SQL2,
+ limit, offset, bindVariableMap);
}
@Override
@@ -138,7 +145,7 @@ public class QueryObjectModelImpl implem
StringBuilder buff = new StringBuilder();
buff.append("select ");
int i;
- if (columns != null) {
+ if (columns != null && columns.length > 0) {
i = 0;
for (Column c : columns) {
if (i++ > 0) {
@@ -170,13 +177,18 @@ public class QueryObjectModelImpl implem
@Override
public String getStoredQueryPath() throws RepositoryException {
- // TODO not implemented yet
- return null;
+ if (storedQueryPath == null) {
+ throw new ItemNotFoundException("Not a stored query");
+ }
+ return storedQueryPath;
}
@Override
public Node storeAsNode(String absPath) throws RepositoryException {
- return queryManager.createQuery(getStatement(), Query.JCR_SQL2).storeAsNode(absPath);
+ Node n = queryManager.createQuery(getStatement(), Query.JCR_SQL2).
+ storeAsNode(absPath);
+ storedQueryPath = n.getPath();
+ return n;
}
public void addBindVariable(BindVariableValueImpl var) {