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/04/05 15:27:09 UTC
svn commit: r1309843 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/query/
test/java/org/apache/jackrabbit/oak/query/
test/resources/org/apache/jackrabbit/oak/query/
Author: thomasm
Date: Thu Apr 5 13:27:08 2012
New Revision: 1309843
URL: http://svn.apache.org/viewvc?rev=1309843&view=rev
Log:
OAK-28 Query implementation (XPath to SQL-2 conversion)
Modified:
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/ResultImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/XPathToSQL2Converter.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
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=1309843&r1=1309842&r2=1309843&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 Apr 5 13:27:08 2012
@@ -261,6 +261,10 @@ public class Query {
}
public ResultImpl executeQuery(String revisionId) {
+ return new ResultImpl(this, revisionId);
+ }
+
+ Iterator<ResultRowImpl> getRows(String revisionId) {
prepare();
Iterator<ResultRowImpl> it;
if (explain) {
@@ -282,7 +286,7 @@ public class Query {
it = list.iterator();
}
}
- return new ResultImpl(this, it);
+ return it;
}
public int compareRows(CoreValue[] orderValues, CoreValue[] orderValues2) {
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=1309843&r1=1309842&r2=1309843&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 Apr 5 13:27:08 2012
@@ -25,6 +25,9 @@ import org.apache.jackrabbit.oak.api.Que
public class QueryEngineImpl implements QueryEngine {
+ static final String SQL2 = "JCR-SQL2";
+ private static final String XPATH = "xpath";
+
private final MicroKernel mk;
private final CoreValueFactory vf = new CoreValueFactory();
private final SQL2Parser parserSQL2;
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultImpl.java?rev=1309843&r1=1309842&r2=1309843&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultImpl.java Thu Apr 5 13:27:08 2012
@@ -28,12 +28,12 @@ import org.apache.jackrabbit.oak.query.a
*/
public class ResultImpl implements Result {
- private final Query query;
- private final Iterator<ResultRowImpl> it;
+ protected final Query query;
+ protected final String revisionId;
- ResultImpl(Query query, Iterator<ResultRowImpl> it) {
+ ResultImpl(Query query, String revisionId) {
this.query = query;
- this.it = it;
+ this.revisionId = revisionId;
}
@Override
@@ -57,8 +57,14 @@ public class ResultImpl implements Resul
}
@Override
- public Iterator<? extends ResultRow> getRows() {
- return it;
+ public Iterable<? extends ResultRow> getRows() {
+ return new Iterable<ResultRowImpl>() {
+
+ @Override
+ public Iterator<ResultRowImpl> iterator() {
+ return query.getRows(revisionId);
+ }
+ };
}
}
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=1309843&r1=1309842&r2=1309843&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 Apr 5 13:27:08 2012
@@ -63,17 +63,21 @@ public class XPathToSQL2Converter {
Expression condition = null;
String from = "nt:base";
ArrayList<Expression> columnList = new ArrayList<Expression>();
- boolean includeChildren = true;
+ boolean children = true;
+ boolean descendants = true;
while (true) {
String nodeType;
if (readIf("/")) {
if (readIf("/")) {
- includeChildren = true;
+ descendants = true;
} else if (readIf("jcr:root")) {
path = "/";
read("/");
+ if (readIf("/")) {
+ descendants = true;
+ }
} else {
- includeChildren = false;
+ descendants = false;
}
if (readIf("*")) {
nodeType = "nt:base";
@@ -82,16 +86,19 @@ public class XPathToSQL2Converter {
read("(");
if (readIf("*")) {
// any
- if (!includeChildren) {
- path = PathUtils.concat(path, "%");
- }
+ children = true;
} else {
+ children = false;
String name = readIdentifier();
path = PathUtils.concat(path, name);
}
- read(",");
- nodeType = readIdentifier();
- from = nodeType;
+ if (readIf(",")) {
+ nodeType = readIdentifier();
+ from = nodeType;
+ } else {
+ nodeType = "nt:base";
+ from = nodeType;
+ }
read(")");
} else if (readIf("@")) {
Property p = new Property(readIdentifier());
@@ -122,15 +129,22 @@ public class XPathToSQL2Converter {
} else if (path.equals("%")) {
// ignore
} else {
- Condition c = new Condition(new Property("jcr:path"), "like", Literal.newString(path));
- if (!includeChildren && path.endsWith("%")) {
- Condition c2 = new Condition(new Property("jcr:path"), "like", Literal.newString(path + '/'));
- c = new Condition(c, "and", new Condition(null, "not", c2));
- } else if (includeChildren && !path.endsWith("%")) {
- Condition c2 = new Condition(new Property("jcr:path"), "like", Literal.newString(path + "/%"));
- c = new Condition(c, "or", c2);
+ if (descendants) {
+ Function f1 = new Function("issamenode");
+ f1.params.add(Literal.newString(path));
+ Function f2 = new Function("isdescendantnode");
+ f2.params.add(Literal.newString(path));
+ Condition c = new Condition(f1, "or", f2);
+ condition = add(condition, c);
+ } else if (children) {
+ Function f = new Function("ischildnode");
+ 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));
+ condition = add(condition, c);
}
- condition = add(condition, c);
}
ArrayList<Order> orderList = new ArrayList<Order>();
if (readIf("order")) {
@@ -163,7 +177,7 @@ public class XPathToSQL2Converter {
buff.append(" from ");
buff.append('[' + from + ']');
if (condition != null) {
- buff.append(" where ").append(condition);
+ buff.append(" where ").append(removeParens(condition.toString()));
}
if (!orderList.isEmpty()) {
buff.append(" order by ");
@@ -211,14 +225,13 @@ public class XPathToSQL2Converter {
c = new Condition(c.left, "is null", null);
a = c;
} else {
- Function f = new Function();
- f.name = "not";
+ Function f = new Function("not");
f.params.add(a);
a = f;
}
read(")");
} else if (readIf("(")) {
- a = new Parenthesis(parseConstraint());
+ a = parseConstraint();
read(")");
} else {
Expression e = parseExpression();
@@ -253,6 +266,10 @@ public class XPathToSQL2Converter {
private Expression parseExpression() throws ParseException {
if (readIf("@")) {
return new Property(readIdentifier());
+ } else if (readIf("true")) {
+ return Literal.newBoolean(true);
+ } else if (readIf("false")) {
+ return Literal.newBoolean(false);
} else if (currentTokenType == VALUE_NUMBER) {
Literal l = Literal.newNumber(currentToken);
read();
@@ -263,6 +280,17 @@ public class XPathToSQL2Converter {
return l;
} else if (currentTokenType == IDENTIFIER) {
String name = readIdentifier();
+ // relative properties
+ if (readIf("/")) {
+ do {
+ if (readIf("@")) {
+ name = name + "/" + readIdentifier();
+ return new Property(name);
+ } else {
+ name = name + "/" + readIdentifier();
+ }
+ } while (readIf("/"));
+ }
read("(");
return parseFunction(name);
} else if (readIf("-")) {
@@ -290,8 +318,7 @@ public class XPathToSQL2Converter {
read(")");
return c;
} else if ("jcr:contains".equals(functionName)) {
- Function f = new Function();
- f.name = "contains";
+ Function f = new Function("contains");
if (readIf(".")) {
// special case: jcr:contains(., expr)
f.params.add(new Literal("*"));
@@ -303,11 +330,15 @@ public class XPathToSQL2Converter {
read(")");
return f;
} else if ("jcr:score".equals(functionName)) {
- Function f = new Function();
- f.name = "score";
+ Function f = new Function("score");
// TODO score: support parameters?
read(")");
return f;
+ } else if ("xs:dateTime".equals(functionName)) {
+ Expression expr = parseExpression();
+ Cast c = new Cast(expr, "date");
+ read(")");
+ return c;
// } else if ("jcr:deref".equals(functionName)) {
// TODO support jcr:deref?
} else {
@@ -625,19 +656,29 @@ public class XPathToSQL2Converter {
}
abstract static class Expression {
+
boolean isCondition() {
return false;
}
+
}
static class Literal extends Expression {
+
final String value;
+
Literal(String value) {
this.value = value;
}
+
+ public static Expression newBoolean(boolean value) {
+ return new Literal("" + value);
+ }
+
static Literal newNumber(String s) {
return new Literal(s);
}
+
static Literal newString(String s) {
return new Literal(SQL2Parser.escapeStringLiteral(s));
}
@@ -646,10 +687,13 @@ public class XPathToSQL2Converter {
public String toString() {
return value;
}
+
}
static class Property extends Expression {
+
final String name;
+
Property(String name) {
this.name = name;
}
@@ -658,24 +702,15 @@ public class XPathToSQL2Converter {
public String toString() {
return '[' + name + ']';
}
- }
-
- static class Parenthesis extends Expression {
- final Expression expr;
- public Parenthesis(Expression expr) {
- this.expr = expr;
- }
- @Override
- public String toString() {
- return "(" + expr + ')';
- }
}
static class Condition extends Expression {
+
final Expression left;
final String operator;
Expression right;
+
Condition(Expression left, String operator, Expression right) {
this.left = left;
this.operator = operator;
@@ -685,20 +720,29 @@ public class XPathToSQL2Converter {
@Override
public String toString() {
return
+ "(" +
(left == null ? "" : left + " ") +
operator +
- (right == null ? "" : " " + right);
+ (right == null ? "" : " " + right) +
+ ")";
}
+
@Override
boolean isCondition() {
return true;
}
+
}
static class Function extends Expression {
- String name;
+
+ final String name;
final ArrayList<Expression> params = new ArrayList<Expression>();
+ Function(String name) {
+ this.name = name;
+ }
+
@Override
public String toString() {
StringBuilder buff = new StringBuilder(name);
@@ -707,18 +751,46 @@ public class XPathToSQL2Converter {
if (i > 0) {
buff.append(", ");
}
- buff.append(params.get(i));
+ buff.append(removeParens(params.get(i).toString()));
}
buff.append(')');
return buff.toString();
}
+
@Override
boolean isCondition() {
return name.equals("contains") || name.equals("not");
}
+
+ }
+
+ static class Cast extends Expression {
+
+ final Expression expr;
+ final String type;
+
+ Cast(Expression expr, String type) {
+ this.expr = expr;
+ this.type = type;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buff = new StringBuilder("cast(");
+ buff.append(removeParens(expr.toString()));
+ buff.append(" as ").append(type).append(')');
+ return buff.toString();
+ }
+
+ @Override
+ boolean isCondition() {
+ return false;
+ }
+
}
static class Order {
+
boolean descending;
Expression expr;
@@ -726,6 +798,14 @@ public class XPathToSQL2Converter {
public String toString() {
return expr + (descending ? " desc" : "");
}
+
+ }
+
+ static String removeParens(String s) {
+ if (s.startsWith("(") && s.endsWith(")")) {
+ return s.substring(1, s.length() - 1);
+ }
+ return s;
}
}
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=1309843&r1=1309842&r2=1309843&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 Apr 5 13:27:08 2012
@@ -26,7 +26,6 @@ import java.util.HashMap;
import java.util.Iterator;
import org.apache.jackrabbit.mk.MicroKernelFactory;
import org.apache.jackrabbit.mk.api.MicroKernel;
-import org.apache.jackrabbit.oak.api.QueryEngine;
import org.apache.jackrabbit.oak.api.ResultRow;
import org.junit.After;
import org.junit.Before;
@@ -65,31 +64,37 @@ public class QueryTest {
@Test
public void bindVariableTest() throws Exception {
- head = mk.commit("/", "+ \"test\": { \"hello\": {\"id\": \"1\"}, \"world\": {\"id\": \"2\"}}", null, null);
+ head = mk.commit("/", "+ \"test\": { \"hello\": {\"id\": \"1\"}, \"world\": {\"id\": \"2\"}}",
+ null, null);
HashMap<String, CoreValue> sv = new HashMap<String, CoreValue>();
CoreValueFactory vf = new CoreValueFactory();
sv.put("id", vf.createValue("1"));
Iterator<? extends ResultRow> result;
- result = qe.executeQuery("select * from [nt:base] where id = $id", QueryEngine.SQL2, sv).getRows();
+ result = qe.executeQuery("select * from [nt:base] where id = $id",
+ QueryEngineImpl.SQL2, sv).getRows().iterator();
assertTrue(result.hasNext());
assertEquals("/test/hello", result.next().getPath());
sv.put("id", vf.createValue("2"));
- result = qe.executeQuery("select * from [nt:base] where id = $id", QueryEngine.SQL2, sv).getRows();
+ result = qe.executeQuery("select * from [nt:base] where id = $id",
+ QueryEngineImpl.SQL2, sv).getRows().iterator();
assertTrue(result.hasNext());
assertEquals("/test/world", result.next().getPath());
- result = qe.executeQuery("explain select * from [nt:base] where id = 1 order by id", QueryEngine.SQL2, null).getRows();
+ result = qe.executeQuery("explain select * from [nt:base] where id = 1 order by id",
+ QueryEngineImpl.SQL2, null).getRows().iterator();
assertTrue(result.hasNext());
- assertEquals("nt:base AS nt:base /* traverse \"//*\" */", result.next().getValue("plan").getString());
+ assertEquals("nt:base AS nt:base /* traverse \"//*\" */",
+ result.next().getValue("plan").getString());
}
private void test(String file) throws Exception {
InputStream in = getClass().getResourceAsStream(file);
LineNumberReader r = new LineNumberReader(new InputStreamReader(in));
- PrintWriter w = new PrintWriter(new OutputStreamWriter(new FileOutputStream("target/" + file)));
+ PrintWriter w = new PrintWriter(new OutputStreamWriter(
+ new FileOutputStream("target/" + file)));
boolean errors = false;
try {
while (true) {
@@ -117,7 +122,8 @@ public class QueryTest {
}
} else if (line.startsWith("select") || line.startsWith("explain")) {
w.println(line);
- Iterator<? extends ResultRow> result = qe.executeQuery(line, QueryEngine.SQL2, null).getRows();
+ Iterator<? extends ResultRow> result = qe.executeQuery(line,
+ QueryEngineImpl.SQL2, null).getRows().iterator();
boolean readEnd = true;
while (result.hasNext()) {
ResultRow row = result.next();
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=1309843&r1=1309842&r2=1309843&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 Thu Apr 5 13:27:08 2012
@@ -42,6 +42,10 @@ select * from [nt:base] as x where isdes
+ "parents": { "p0": {"id": "0"}, "p1": {"id": "1"}, "p2": {"id": "2"}}
+ "children": { "c1": {"p": "1"}, "c2": {"p": "1"}, "c3": {"p": "2"}, "c4": {"p": "3"}}
+# relative property
+select * from [nt:base] where [c1/p] = '1'
+/children
+
select * from [nt:base] as p where p.[jcr:path] = '/parents'
/parents
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=1309843&r1=1309842&r2=1309843&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 Apr 5 13:27:08 2012
@@ -3,6 +3,56 @@
# * lines starting with "xpath" are xpath queries, followed by expected sql2 query
# * use ascii character only
+xpath /jcr:root//*[jcr:contains(., 'test')] order by @jcr:score
+select * from [nt:base] where contains(*, 'test') and (issamenode('/') or isdescendantnode('/')) order by [jcr:score]
+
+xpath /jcr:root//element(*, test)
+select * from [test] where issamenode('/') or isdescendantnode('/')
+
+xpath /jcr:root//element(*, test)
+select * from [test] where issamenode('/') or isdescendantnode('/')
+
+xpath /jcr:root//element(*, user)[test/@jcr:primaryType]
+select * from [user] where ([test/jcr:primaryType] is not null) and (issamenode('/') or isdescendantnode('/'))
+
+xpath /jcr:root/content//*[(@sling:resourceType = 'start')]
+select * from [nt:base] where ([sling:resourceType] = 'start') and (issamenode('/content') or isdescendantnode('/content'))
+
+xpath /jcr:root/content//*[(@sling:resourceType = 'page')]
+select * from [nt:base] where ([sling:resourceType] = 'page') and (issamenode('/content') or 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 * 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 (issamenode('/content') or isdescendantnode('/content'))
+
+xpath /jcr:root/content/campaigns//*[@jcr:primaryType='Page'] order by jcr:content/@lastModified descending
+select * from [nt:base] where ([jcr:primaryType] = 'Page') and (issamenode('/content/campaigns') or 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 * 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 (issamenode('/content/campaigns') or isdescendantnode('/content/campaigns')) order by [onTime]
+
+xpath /jcr:root/content/dam//element(*, asset)[jcr:content/metadata/@dam:scene]
+select * from [asset] where ([jcr:content/metadata/dam:scene] is not null) and (issamenode('/content/dam') or isdescendantnode('/content/dam'))
+
+xpath /jcr:root/etc/cloud//*[(@sling:resourceType = 'framework')]
+select * from [nt:base] where ([sling:resourceType] = 'framework') and (issamenode('/etc/cloud') or isdescendantnode('/etc/cloud'))
+
+xpath /jcr:root/etc/cloud//*[(@sling:resourceType = 'analytics')]
+select * from [nt:base] where ([sling:resourceType] = 'analytics') and (issamenode('/etc/cloud') or isdescendantnode('/etc/cloud'))
+
+xpath /jcr:root/etc/reports//*[@jcr:primaryType='Page'] order by jcr:content/@lastModified descending
+select * from [nt:base] where ([jcr:primaryType] = 'Page') and (issamenode('/etc/reports') or isdescendantnode('/etc/reports')) order by [jcr:content/lastModified] desc
+
+xpath /jcr:root/etc/segment//*[@jcr:primaryType='Page'] order by jcr:content/@lastModified descending
+select * from [nt:base] where ([jcr:primaryType] = 'Page') and (issamenode('/etc/segment') or 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 * from [Item] where (([meta/archived] is null) and not([meta/archived] = true)) and (issamenode('/etc/workflow') or isdescendantnode('/etc/workflow'))
+
+xpath /jcr:root/home//element(*)
+select * from [nt:base] where issamenode('/home') or isdescendantnode('/home')
+
+# other queries
+
xpath //*
select * from [nt:base]
@@ -16,16 +66,16 @@ xpath //element(*, my:type)/(@my:title |
select [my:title], [my:text] from [my:type]
xpath /jcr:root/nodes//element(*, my:type)
-select * from [my:type] where [jcr:path] like '/nodes' or [jcr:path] like '/nodes/%'
+select * from [my:type] where issamenode('/nodes') or isdescendantnode('/nodes')
xpath /jcr:root/some/element(nodes, my:type)
-select * from [my:type] where [jcr:path] like '/some/nodes'
+select * from [my:type] where [jcr:path] = '/some/nodes'
xpath /jcr:root/some/nodes/element(*, my:type)
-select * from [my:type] where [jcr:path] like '/some/nodes/%' and not [jcr:path] like '/some/nodes/%/'
+select * from [my:type] where ischildnode('/some/nodes')
xpath /jcr:root/some/nodes//element(*, my:type)
-select * from [my:type] where [jcr:path] like '/some/nodes' or [jcr:path] like '/some/nodes/%'
+select * from [my:type] where issamenode('/some/nodes') or isdescendantnode('/some/nodes')
xpath //element(*, my:type)[@my:title = 'JSR 170']
select * from [my:type] where [my:title] = 'JSR 170'
@@ -58,13 +108,13 @@ xpath //element(*, my:type)[@my:value <>
select * from [my:type] where [my:value] <> 'Joe''s Caffee'
xpath //element(*, my:type)[(not(@my:title) and @my:subject)]
-select * from [my:type] where ([my:title] is null and [my:subject] is not null)
+select * 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 * from [my:type] where [my:title] is null or [my:subject] is not null
+select * 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 * from [my:type] where not([my:value] > 0 and [my:value] < 100)
+select * from [my:type] where not(([my:value] > 0) and ([my:value] < 100))
xpath //element(*, my:type) order by @jcr:lastModified
select * from [my:type] order by [jcr:lastModified]
@@ -94,13 +144,13 @@ xpath //element(*, my:type)[@my:value =
invalid: Query: //element(*, my:type)[@my:value = +'x'(*)]
xpath //element(*, my:type)[@my:value = ['x']
-invalid: Query: //element(*, my:type)[@my:value = [(*)'x']; expected: @, -, +
+invalid: Query: //element(*, my:type)[@my:value = [(*)'x']; expected: @, true, false, -, +
xpath //element(*, my:type)[jcr:strike(@title,'%Java%')]
invalid: Query: //element(*, my:type)[jcr:strike(@(*)title,'%Java%')]; expected: jcr:like | jcr:contains | jcr:score | jcr:deref
xpath //element(*, my:type)[
-invalid: Query: //element(*, my:type)(*)[; expected: not, (, @, -, +
+invalid: Query: //element(*, my:type)(*)[; expected: not, (, @, true, false, -, +
xpath //element(*, my:type)[@my:value >= .]
-invalid: Query: //element(*, my:type)[@my:value >= .(*)]; expected: @, -, +
+invalid: Query: //element(*, my:type)[@my:value >= .(*)]; expected: @, true, false, -, +