Author: rhauch
Date: 2009-12-31 16:36:01 -0500 (Thu, 31 Dec 2009)
New Revision: 1508
Added:
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/query/HasValueQuery.java
Modified:
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryQueryManager.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/xpath/XPathToQueryTranslator.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrQueryManagerTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/xpath/XPathToQueryTranslatorTest.java
trunk/dna-jcr/src/test/resources/tck/repositoryForTckTests.xml
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/AbstractLuceneSearchEngine.java
trunk/extensions/dna-search-lucene/src/test/java/org/jboss/dna/search/lucene/LuceneSearchEngineTest.java
Log:
DNA-468 This commit includes several fixes for the XPath query functionality, some fixes
for several tests, and some new unit tests. At this point there are still some
outstanding issues with certain XPath tests, but these are being tracked under DNA-612 and
DNA-613.
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java 2009-12-31 18:53:06
UTC (rev 1507)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java 2009-12-31 21:36:01
UTC (rev 1508)
@@ -297,6 +297,10 @@
this.variables = null;
}
+ protected QueryCommand getCommand() {
+ return query;
+ }
+
/**
* {@inheritDoc}
*
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryQueryManager.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryQueryManager.java 2009-12-31
18:53:06 UTC (rev 1507)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryQueryManager.java 2009-12-31
21:36:01 UTC (rev 1508)
@@ -26,6 +26,7 @@
import java.io.File;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.jcr.RepositoryException;
@@ -287,6 +288,8 @@
};
this.queryEngine = new QueryEngine(planner, optimizer, processor);
+ // Index any existing content ...
+ reindexContent();
}
protected void process( Changes changes ) {
@@ -321,11 +324,13 @@
*/
@Override
public void reindexContent() {
- // Index the existing content ...
- Graph graph = Graph.create(sourceName, connectionFactory, context);
+ // Get the workspace names ...
+ Set<String> workspaces = Graph.create(sourceName, connectionFactory,
context).getWorkspaces();
+
+ // Index the existing content (this obtains a connection and possibly locks
the source) ...
SearchEngineIndexer indexer = new SearchEngineIndexer(context, searchEngine,
connectionFactory);
try {
- for (String workspace : graph.getWorkspaces()) {
+ for (String workspace : workspaces) {
indexer.index(workspace);
}
} finally {
Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/xpath/XPathToQueryTranslator.java
===================================================================
---
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/xpath/XPathToQueryTranslator.java 2009-12-31
18:53:06 UTC (rev 1507)
+++
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/xpath/XPathToQueryTranslator.java 2009-12-31
21:36:01 UTC (rev 1508)
@@ -30,7 +30,6 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
-import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.property.PropertyType;
import org.jboss.dna.graph.query.QueryBuilder;
import org.jboss.dna.graph.query.QueryBuilder.ConstraintBuilder;
@@ -38,7 +37,6 @@
import org.jboss.dna.graph.query.model.QueryCommand;
import org.jboss.dna.graph.query.model.TypeSystem;
import org.jboss.dna.graph.query.parse.InvalidQueryException;
-import org.jboss.dna.jcr.JcrNtLexicon;
import org.jboss.dna.jcr.xpath.XPath.And;
import org.jboss.dna.jcr.xpath.XPath.AttributeNameTest;
import org.jboss.dna.jcr.xpath.XPath.AxisStep;
@@ -153,12 +151,12 @@
AxisStep axis = (AxisStep)step;
NodeTest nodeTest = axis.getNodeTest();
if (nodeTest instanceof NameTest) {
- if (appliesToPathConstraint(axis.getPredicates())) {
- // Can go into the path constraint ...
+ NameTest nameTest = (NameTest)nodeTest;
+ if (!nameTest.isWildcard()) {
path.add(step);
- } else {
+ }
+ if (!appliesToPathConstraint(axis.getPredicates())) {
// The constraints are more complicated, so we need to define a
new source/table ...
- // path.add(step);
tableName = translateSource(tableName, path, where);
translatePredicates(axis.getPredicates(), tableName, where);
path.clear();
@@ -302,19 +300,18 @@
ConstraintBuilder where ) {
if (path.size() == 0) {
// This is a query against the root node ...
- ExecutionContext context = new ExecutionContext();
String alias = newAlias();
- builder.from(JcrNtLexicon.BASE.getString(context.getNamespaceRegistry()) +
" AS " + alias);
+ builder.from("nt:base AS " + alias);
where.path(alias).isEqualTo("/");
return alias;
}
String alias = newAlias();
if (tableName != null) {
// This is after some element(...) steps, so we need to join ...
- builder.joinAllNodesAs(alias);
+ builder.join("nt:base AS " + alias);
} else {
// This is the only part of the query ...
- builder.fromAllNodesAs(alias);
+ builder.from("nt:base AS " + alias);
}
tableName = alias;
if (path.size() == 1 && path.get(0).collapse() instanceof NameTest) {
@@ -341,7 +338,7 @@
NameTest typeName = elementTest.getTypeName();
if (typeName.isWildcard()) {
tableName = newAlias();
- builder.fromAllNodesAs(tableName);
+ builder.from("nt:base AS " + tableName);
} else {
if (typeName.getLocalTest() == null) {
throw new InvalidQueryException(
@@ -417,7 +414,7 @@
// This adds the criteria that the child node exists ...
NameTest childName = (NameTest)predicate;
String alias = newAlias();
- builder.joinAllNodesAs(alias).onChildNode(tableName, alias);
+ builder.join("nt:base AS " + alias).onChildNode(tableName, alias);
if (!childName.isWildcard())
where.nodeName(alias).isEqualTo(nameFrom(childName));
tableName = alias;
} else if (predicate instanceof Comparison) {
@@ -535,7 +532,7 @@
} else if (param1 instanceof NameTest) {
// refers to child node, so we need to add a join ...
String alias = newAlias();
- builder.joinAllNodesAs(alias).onChildNode(tableName, alias);
+ builder.join("nt:base AS " + alias).onChildNode(tableName,
alias);
// Now add the criteria ...
where.search(alias, value);
tableName = alias;
@@ -583,7 +580,7 @@
// Special case where this is similar to '[a/@id]'
NameTest childName = (NameTest)firstStep;
String alias = newAlias();
- builder.joinAllNodesAs(alias).onChildNode(tableName, alias);
+ builder.join("nt:base AS " + alias).onChildNode(tableName,
alias);
if (!childName.isWildcard()) {
where.nodeName(alias).isEqualTo(nameFrom(childName));
}
@@ -592,12 +589,12 @@
if (firstStep instanceof DescendantOrSelf) {
// Special case where this is similar to '[a/@id]'
String alias = newAlias();
- builder.joinAllNodesAs(alias).onDescendant(tableName, alias);
+ builder.join("nt:base AS " + alias).onDescendant(tableName,
alias);
return translatePredicate(new PathExpression(true, steps.subList(1,
steps.size())), alias, where);
}
// Add the join ...
String alias = newAlias();
- builder.joinAllNodesAs(alias).onDescendant(tableName, alias);
+ builder.join("nt:base AS " + alias).onDescendant(tableName,
alias);
// Now add the criteria ...
translatePathExpressionConstraint(pathExpr, where, alias);
} else {
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrQueryManagerTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrQueryManagerTest.java 2009-12-31
18:53:06 UTC (rev 1507)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrQueryManagerTest.java 2009-12-31
21:36:01 UTC (rev 1508)
@@ -44,6 +44,7 @@
import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.Path.Segment;
+import org.jboss.dna.jcr.JcrQueryManager.JcrQuery;
import org.jboss.dna.jcr.JcrRepository.Option;
import org.jboss.dna.jcr.JcrRepository.QueryLanguage;
import org.junit.After;
@@ -79,6 +80,7 @@
private static JcrEngine engine;
private static JcrRepository repository;
private Session session;
+ private boolean print;
@BeforeClass
public static void beforeAll() throws Exception {
@@ -110,6 +112,13 @@
stream.close();
}
+ // Create a branch that contains some same-name-siblings ...
+ Node other = session.getRootNode().addNode("Other",
"nt:unstructured");
+ other.addNode("NodeA", "nt:unstructured");
+ other.addNode("NodeA", "nt:unstructured");
+ other.addNode("NodeA", "nt:unstructured");
+ session.save();
+
// Prime creating a first XPath query and SQL query ...
session.getWorkspace().getQueryManager().createQuery("//element(*,nt:unstructured)",
Query.XPATH);
session.getWorkspace().getQueryManager().createQuery("SELECT * FROM
[nt:base]", JcrRepository.QueryLanguage.SQL);
@@ -131,6 +140,7 @@
@Before
public void beforeEach() throws Exception {
+ print = false;
// Obtain a session using the anonymous login capability, which we granted READ
privilege
session = repository.login();
}
@@ -162,6 +172,21 @@
return result;
}
+ protected void assertResults( Query query,
+ QueryResult result,
+ long numberOfResults ) throws RepositoryException {
+ assertThat(query, is(notNullValue()));
+ assertThat(result, is(notNullValue()));
+ if (print) {
+ System.out.println();
+ System.out.println(query.getLanguage() + ": " +
query.getStatement());
+ System.out.println(" --> : " + ((JcrQuery)query).getCommand());
+ System.out.println(result);
+ }
+ assertThat(result.getNodes().getSize(), is(numberOfResults));
+ assertThat(result.getRows().getSize(), is(numberOfResults));
+ }
+
protected void assertResultsHaveColumns( QueryResult result,
String... columnNames ) throws
RepositoryException {
Set<String> expectedNames = new HashSet<String>();
@@ -187,7 +212,7 @@
assertThat(node.hasNode("Sports"), is(true));
assertThat(node.hasNode("Utility"), is(true));
assertThat(node.hasNode("Hybrid"), is(true));
-
System.out.println(node.getNode("Hybrid").getNodes().nextNode().getPath());
+ //
System.out.println(node.getNode("Hybrid").getNodes().nextNode().getPath());
assertThat(node.hasNode("Hybrid/Toyota Prius"), is(true));
assertThat(node.getPrimaryNodeType().getName(),
is("nt:unstructured"));
}
@@ -207,8 +232,8 @@
assertThat(query, is(notNullValue()));
QueryResult result = query.execute();
assertThat(result, is(notNullValue()));
+ assertResults(query, result, 22);
assertResultsHaveColumns(result, "jcr:primaryType");
- // System.out.println(result);
}
//
----------------------------------------------------------------------------------------------------------------
@@ -219,6 +244,7 @@
public void shouldBeAbleToCreateXPathQuery() throws RepositoryException {
Query query =
session.getWorkspace().getQueryManager().createQuery("//element(*,nt:unstructured)",
Query.XPATH);
assertThat(query, is(notNullValue()));
+ assertResults(query, query.execute(), 21);
}
@Test
@@ -226,7 +252,7 @@
Query query =
session.getWorkspace().getQueryManager().createQuery("//element(*,nt:base)",
Query.XPATH);
assertThat(query, is(notNullValue()));
QueryResult result = query.execute();
- assertThat(result, is(notNullValue()));
+ assertResults(query, result, 22);
assertResultsHaveColumns(result, "jcr:primaryType",
"jcr:path", "jcr:score");
}
@@ -235,17 +261,39 @@
Query query =
session.getWorkspace().getQueryManager().createQuery("//element(*,nt:unstructured)",
Query.XPATH);
assertThat(query, is(notNullValue()));
QueryResult result = query.execute();
+ assertResults(query, result, 21);
assertThat(result, is(notNullValue()));
assertResultsHaveColumns(result, "jcr:primaryType",
"jcr:path", "jcr:score");
}
@Test
+ public void shouldBeAbleToExecuteXPathQueryToFindSameNameSiblingsByIndex() throws
RepositoryException {
+ Query query =
session.getWorkspace().getQueryManager().createQuery("/jcr:root/Other/NodeA",
Query.XPATH);
+ assertThat(query, is(notNullValue()));
+ QueryResult result = query.execute();
+ print = true;
+ assertResults(query, result, 1);
+ assertThat(result, is(notNullValue()));
+ assertThat(result.getNodes().nextNode().getIndex(), is(1));
+ assertResultsHaveColumns(result, "jcr:primaryType",
"jcr:path", "jcr:score");
+
+ query =
session.getWorkspace().getQueryManager().createQuery("/jcr:root/Other/NodeA[2]",
Query.XPATH);
+ assertThat(query, is(notNullValue()));
+ result = query.execute();
+ print = true;
+ assertResults(query, result, 1);
+ assertThat(result, is(notNullValue()));
+ assertThat(result.getNodes().nextNode().getIndex(), is(2));
+ assertResultsHaveColumns(result, "jcr:primaryType",
"jcr:path", "jcr:score");
+ }
+
+ @Test
public void shouldBeAbleToExecuteXPathQueryToFindAllCarNodes() throws
RepositoryException {
Query query =
session.getWorkspace().getQueryManager().createQuery("//element(*,car:Car)",
Query.XPATH);
assertThat(query, is(notNullValue()));
QueryResult result = query.execute();
assertThat(result, is(notNullValue()));
- // System.out.println(result);
+ assertResults(query, result, 12);
assertResultsHaveColumns(result,
"jcr:primaryType",
"jcr:path",
@@ -268,18 +316,27 @@
Query query =
session.getWorkspace().getQueryManager().createQuery("/jcr:root", Query.XPATH);
assertThat(query, is(notNullValue()));
QueryResult result = query.execute();
+ assertResults(query, result, 1);
+ assertResultsHaveColumns(result, "jcr:primaryType",
"jcr:path", "jcr:score");
+ }
+
+ @Test
+ public void shouldBeAbleToExecuteXPathQueryToFindChildOfRootNode() throws
RepositoryException {
+ Query query =
session.getWorkspace().getQueryManager().createQuery("/jcr:root/Cars",
Query.XPATH);
+ assertThat(query, is(notNullValue()));
+ QueryResult result = query.execute();
assertThat(result, is(notNullValue()));
- // System.out.println(result);
+ assertResults(query, result, 1);
assertResultsHaveColumns(result, "jcr:primaryType",
"jcr:path", "jcr:score");
}
- // @Test
- // public void shouldBeAbleToExecuteXPathQueryToFindChildOfRootNode() throws
RepositoryException {
- // Query query =
session.getWorkspace().getQueryManager().createQuery("/jcr:root/Cars",
Query.XPATH);
- // assertThat(query, is(notNullValue()));
- // QueryResult result = query.execute();
- // assertThat(result, is(notNullValue()));
- // System.out.println(result);
- // assertResultsHaveColumns(result, "jcr:primaryType",
"jcr:path", "jcr:score");
- // }
+ @Test
+ public void shouldBeAbleToExecuteXPathQueryToFindChildOfRootNodeWithTypeCriteria()
throws RepositoryException {
+ Query query =
session.getWorkspace().getQueryManager().createQuery("/jcr:root/Cars[@jcr:primaryType]",
Query.XPATH);
+ assertThat(query, is(notNullValue()));
+ QueryResult result = query.execute();
+ assertThat(result, is(notNullValue()));
+ assertResults(query, result, 1);
+ assertResultsHaveColumns(result, "jcr:primaryType",
"jcr:path", "jcr:score");
+ }
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-12-31 18:53:06 UTC
(rev 1507)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java 2009-12-31 21:36:01 UTC
(rev 1508)
@@ -177,7 +177,7 @@
addTestSuite(org.apache.jackrabbit.test.api.RepositoryLoginTest.class);
// These might not all be level one tests
- //
addTestSuite(org.apache.jackrabbit.test.api.query.XPathPosIndexTest.class);
+ addTestSuite(org.apache.jackrabbit.test.api.query.XPathPosIndexTest.class);
//
addTestSuite(org.apache.jackrabbit.test.api.query.XPathDocOrderTest.class);
//
addTestSuite(org.apache.jackrabbit.test.api.query.XPathOrderByTest.class);
addTestSuite(org.apache.jackrabbit.test.api.query.XPathJcrPathTest.class);
@@ -188,7 +188,7 @@
addTestSuite(org.apache.jackrabbit.test.api.query.GetSupportedQueryLanguagesTest.class);
addTestSuite(org.apache.jackrabbit.test.api.query.GetPropertyNamesTest.class);
addTestSuite(org.apache.jackrabbit.test.api.query.PredicatesTest.class);
- //
addTestSuite(org.apache.jackrabbit.test.api.query.SimpleSelectionTest.class);
+
addTestSuite(org.apache.jackrabbit.test.api.query.SimpleSelectionTest.class);
// The tests in this suite are level one
addTest(org.apache.jackrabbit.test.api.nodetype.TestAll.suite());
Modified:
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/xpath/XPathToQueryTranslatorTest.java
===================================================================
---
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/xpath/XPathToQueryTranslatorTest.java 2009-12-31
18:53:06 UTC (rev 1507)
+++
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/xpath/XPathToQueryTranslatorTest.java 2009-12-31
21:36:01 UTC (rev 1508)
@@ -65,12 +65,12 @@
@Test
public void shouldTranslateFromXPathOfAnyNode() {
- assertThat(xpath("//element(*)"), isSql("SELECT * FROM
__ALLNODES__ AS nodeSet1"));
- assertThat(xpath("/jcr:root//element(*)"), isSql("SELECT * FROM
__ALLNODES__ AS nodeSet1"));
- assertThat(xpath("//*"), isSql("SELECT * FROM __ALLNODES__ AS
nodeSet1"));
- assertThat(xpath("/jcr:root//*"), isSql("SELECT * FROM
__ALLNODES__ AS nodeSet1"));
- assertThat(xpath("//."), isSql("SELECT * FROM __ALLNODES__ AS
nodeSet1"));
- assertThat(xpath("/jcr:root//."), isSql("SELECT * FROM
__ALLNODES__ AS nodeSet1"));
+ assertThat(xpath("//element(*)"), isSql("SELECT * FROM [nt:base]
AS nodeSet1"));
+ assertThat(xpath("/jcr:root//element(*)"), isSql("SELECT * FROM
[nt:base] AS nodeSet1"));
+ assertThat(xpath("//*"), isSql("SELECT * FROM [nt:base] AS
nodeSet1"));
+ assertThat(xpath("/jcr:root//*"), isSql("SELECT * FROM [nt:base]
AS nodeSet1"));
+ assertThat(xpath("//."), isSql("SELECT * FROM [nt:base] AS
nodeSet1"));
+ assertThat(xpath("/jcr:root//."), isSql("SELECT * FROM [nt:base]
AS nodeSet1"));
}
@Test
@@ -80,69 +80,70 @@
@Test
public void shouldTranslateFromXPathContainingExplicitPath() {
- assertThat(xpath("/jcr:root/a"), isSql("SELECT * FROM __ALLNODES__
AS nodeSet1 WHERE PATH(nodeSet1) = '/a'"));
- assertThat(xpath("/jcr:root/a/b"), isSql("SELECT * FROM
__ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b'"));
- assertThat(xpath("/jcr:root/a/b/c"), isSql("SELECT * FROM
__ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b/c'"));
- assertThat(xpath("/jcr:root/a/b/c/d"), isSql("SELECT * FROM
__ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b/c/d'"));
+ assertThat(xpath("/jcr:root/a"), isSql("SELECT * FROM [nt:base] AS
nodeSet1 WHERE PATH(nodeSet1) = '/a'"));
+ assertThat(xpath("/jcr:root/a/b"), isSql("SELECT * FROM [nt:base]
AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b'"));
+ assertThat(xpath("/jcr:root/a/b/c"), isSql("SELECT * FROM
[nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b/c'"));
+ assertThat(xpath("/jcr:root/a/b/c/d"), isSql("SELECT * FROM
[nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b/c/d'"));
}
@Test
public void shouldTranslateFromXPathContainingExplicitPathWithChildNumbers() {
- assertThat(xpath("/jcr:root/a[2]/b"), isSql("SELECT * FROM
__ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a[2]/b'"));
- assertThat(xpath("/jcr:root/a/b[3]"), isSql("SELECT * FROM
__ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b[3]'"));
- assertThat(xpath("/jcr:root/a[2]/b[3]"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE
PATH(nodeSet1) = '/a[2]/b[3]'"));
+ assertThat(xpath("/jcr:root/a[2]/b"), isSql("SELECT * FROM
[nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a[2]/b'"));
+ assertThat(xpath("/jcr:root/a/b[3]"), isSql("SELECT * FROM
[nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b[3]'"));
+ assertThat(xpath("/jcr:root/a[2]/b[3]"), isSql("SELECT * FROM
[nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a[2]/b[3]'"));
}
@Test
public void shouldTranslateFromXPathContainingExplicitPathWithWildcardChildNumbers()
{
- assertThat(xpath("/jcr:root/a[*]/b"), isSql("SELECT * FROM
__ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b'"));
- assertThat(xpath("/jcr:root/a/b[*]"), isSql("SELECT * FROM
__ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b'"));
- assertThat(xpath("/jcr:root/a[*]/b[*]"), isSql("SELECT * FROM
__ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b'"));
+ assertThat(xpath("/jcr:root/a[*]/b"), isSql("SELECT * FROM
[nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b'"));
+ assertThat(xpath("/jcr:root/a/b[*]"), isSql("SELECT * FROM
[nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b'"));
+ assertThat(xpath("/jcr:root/a[*]/b[*]"), isSql("SELECT * FROM
[nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b'"));
}
@Test
public void shouldTranslateFromXPathContainingPathWithDescendantOrSelf() {
assertThat(xpath("/jcr:root/a/b//c"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE
PATH(nodeSet1) = '/a/b/c' OR PATH(nodeSet1) LIKE '/a/b/%/c'"));
+ isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) =
'/a/b/c' OR PATH(nodeSet1) LIKE '/a/b/%/c'"));
assertThat(xpath("/jcr:root/a/b[2]//c"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE
PATH(nodeSet1) = '/a/b[2]/c' OR PATH(nodeSet1) LIKE
'/a/b[2]/%/c'"));
+ isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) =
'/a/b[2]/c' OR PATH(nodeSet1) LIKE '/a/b[2]/%/c'"));
assertThat(xpath("/jcr:root/a/b//c[4]"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE
PATH(nodeSet1) = '/a/b/c[4]' OR PATH(nodeSet1) LIKE
'/a/b/%/c[4]'"));
+ isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) =
'/a/b/c[4]' OR PATH(nodeSet1) LIKE '/a/b/%/c[4]'"));
assertThat(xpath("/jcr:root/a/b[2]//c[4]"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE
PATH(nodeSet1) = '/a/b[2]/c[4]' OR PATH(nodeSet1) LIKE
'/a/b[2]/%/c[4]'"));
+ isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) =
'/a/b[2]/c[4]' OR PATH(nodeSet1) LIKE '/a/b[2]/%/c[4]'"));
}
@Test
public void shouldTranslateFromXPathContainingPathWithMultipleDescendantOrSelf() {
assertThat(xpath("/jcr:root/a/b//c//d"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE
(((PATH(nodeSet1) = '/a/b/c/d' OR PATH(nodeSet1) LIKE '/a/b/%/c/d') OR
PATH(nodeSet1) LIKE '/a/b/c/%/d') OR PATH(nodeSet1) LIKE
'/a/b/%/c/%/d')"));
+ isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE
(((PATH(nodeSet1) = '/a/b/c/d' OR PATH(nodeSet1) LIKE '/a/b/%/c/d') OR
PATH(nodeSet1) LIKE '/a/b/c/%/d') OR PATH(nodeSet1) LIKE
'/a/b/%/c/%/d')"));
}
@Test
public void shouldTranslateFromXPathContainingPredicatesUsingRelativePaths() {
assertThat(xpath("//element(*,my:type)[a/@id]"),
- isSql("SELECT * FROM [my:type] JOIN __ALLNODES__ as nodeSet1 ON
ISCHILDNODE(nodeSet1,[my:type]) WHERE NAME(nodeSet1) = 'a' AND nodeSet1.id IS NOT
NULL"));
+ isSql("SELECT * FROM [my:type] JOIN [nt:base] as nodeSet1 ON
ISCHILDNODE(nodeSet1,[my:type]) WHERE NAME(nodeSet1) = 'a' AND nodeSet1.id IS NOT
NULL"));
assertThat(xpath("//element(*,my:type)[a/b/@id]"),
- isSql("SELECT * FROM [my:type] JOIN __ALLNODES__ as nodeSet1 ON
ISCHILDNODE(nodeSet1,[my:type]) JOIN __ALLNODES__ as nodeSet2 ON
ISCHILDNODE(nodeSet2,nodeSet1) WHERE (NAME(nodeSet1) = 'a' AND NAME(nodeSet2) =
'b') AND nodeSet2.id IS NOT NULL"));
+ isSql("SELECT * FROM [my:type] JOIN [nt:base] as nodeSet1 ON
ISCHILDNODE(nodeSet1,[my:type]) JOIN [nt:base] as nodeSet2 ON
ISCHILDNODE(nodeSet2,nodeSet1) WHERE (NAME(nodeSet1) = 'a' AND NAME(nodeSet2) =
'b') AND nodeSet2.id IS NOT NULL"));
assertThat(xpath("//element(*,my:type)[a/b/((@id and @name) or
not(@address))]"),
- isSql("SELECT * FROM [my:type] JOIN __ALLNODES__ as nodeSet1 ON
ISCHILDNODE(nodeSet1,[my:type]) JOIN __ALLNODES__ as nodeSet2 ON
ISCHILDNODE(nodeSet2,nodeSet1) WHERE (NAME(nodeSet1) = 'a' AND NAME(nodeSet2) =
'b') AND ((nodeSet2.id IS NOT NULL and nodeSet2.name IS NOT NULL) OR
(NOT(nodeSet2.address IS NOT NULL)))"));
+ isSql("SELECT * FROM [my:type] JOIN [nt:base] as nodeSet1 ON
ISCHILDNODE(nodeSet1,[my:type]) JOIN [nt:base] as nodeSet2 ON
ISCHILDNODE(nodeSet2,nodeSet1) WHERE (NAME(nodeSet1) = 'a' AND NAME(nodeSet2) =
'b') AND ((nodeSet2.id IS NOT NULL and nodeSet2.name IS NOT NULL) OR
(NOT(nodeSet2.address IS NOT NULL)))"));
assertThat(xpath("//element(*,my:type)[./a/b/((@id and @name) or
not(@address))]"),
- isSql("SELECT * FROM [my:type] JOIN __ALLNODES__ as nodeSet1 ON
ISCHILDNODE(nodeSet1,[my:type]) JOIN __ALLNODES__ as nodeSet2 ON
ISCHILDNODE(nodeSet2,nodeSet1) WHERE (NAME(nodeSet1) = 'a' AND NAME(nodeSet2) =
'b') AND ((nodeSet2.id IS NOT NULL and nodeSet2.name IS NOT NULL) OR
(NOT(nodeSet2.address IS NOT NULL)))"));
+ isSql("SELECT * FROM [my:type] JOIN [nt:base] as nodeSet1 ON
ISCHILDNODE(nodeSet1,[my:type]) JOIN [nt:base] as nodeSet2 ON
ISCHILDNODE(nodeSet2,nodeSet1) WHERE (NAME(nodeSet1) = 'a' AND NAME(nodeSet2) =
'b') AND ((nodeSet2.id IS NOT NULL and nodeSet2.name IS NOT NULL) OR
(NOT(nodeSet2.address IS NOT NULL)))"));
assertThat(xpath("//element(*,my:type)[a/b/((@id and @name) or
not(jcr:contains(@desc,'rock star')))]"),
- isSql("SELECT * FROM [my:type] JOIN __ALLNODES__ as nodeSet1 ON
ISCHILDNODE(nodeSet1,[my:type]) JOIN __ALLNODES__ as nodeSet2 ON
ISCHILDNODE(nodeSet2,nodeSet1) WHERE (NAME(nodeSet1) = 'a' AND NAME(nodeSet2) =
'b') AND ((nodeSet2.id IS NOT NULL and nodeSet2.name IS NOT NULL) OR
(NOT(CONTAINS(nodeSet2.desc,'rock star'))))"));
+ isSql("SELECT * FROM [my:type] JOIN [nt:base] as nodeSet1 ON
ISCHILDNODE(nodeSet1,[my:type]) JOIN [nt:base] as nodeSet2 ON
ISCHILDNODE(nodeSet2,nodeSet1) WHERE (NAME(nodeSet1) = 'a' AND NAME(nodeSet2) =
'b') AND ((nodeSet2.id IS NOT NULL and nodeSet2.name IS NOT NULL) OR
(NOT(CONTAINS(nodeSet2.desc,'rock star'))))"));
assertThat(xpath("//element(*,my:type)[*/@id]"),
- isSql("SELECT * FROM [my:type] JOIN __ALLNODES__ as nodeSet1 ON
ISCHILDNODE(nodeSet1,[my:type]) WHERE nodeSet1.id IS NOT NULL"));
+ isSql("SELECT * FROM [my:type] JOIN [nt:base] as nodeSet1 ON
ISCHILDNODE(nodeSet1,[my:type]) WHERE nodeSet1.id IS NOT NULL"));
assertThat(xpath("//element(*,my:type)[*/*/@id]"),
- isSql("SELECT * FROM [my:type] JOIN __ALLNODES__ as nodeSet1 ON
ISCHILDNODE(nodeSet1,[my:type]) JOIN __ALLNODES__ as nodeSet2 ON
ISCHILDNODE(nodeSet2,nodeSet1) WHERE nodeSet2.id IS NOT NULL"));
+ isSql("SELECT * FROM [my:type] JOIN [nt:base] as nodeSet1 ON
ISCHILDNODE(nodeSet1,[my:type]) JOIN [nt:base] as nodeSet2 ON
ISCHILDNODE(nodeSet2,nodeSet1) WHERE nodeSet2.id IS NOT NULL"));
assertThat(xpath("//element(*,my:type)[./*/*/@id]"),
- isSql("SELECT * FROM [my:type] JOIN __ALLNODES__ as nodeSet1 ON
ISCHILDNODE(nodeSet1,[my:type]) JOIN __ALLNODES__ as nodeSet2 ON
ISCHILDNODE(nodeSet2,nodeSet1) WHERE nodeSet2.id IS NOT NULL"));
+ isSql("SELECT * FROM [my:type] JOIN [nt:base] as nodeSet1 ON
ISCHILDNODE(nodeSet1,[my:type]) JOIN [nt:base] as nodeSet2 ON
ISCHILDNODE(nodeSet2,nodeSet1) WHERE nodeSet2.id IS NOT NULL"));
assertThat(xpath("//element(*,my:type)[.//@id]"),
- isSql("SELECT * FROM [my:type] JOIN __ALLNODES__ as nodeSet1 ON
ISDESCENDANTNODE(nodeSet1,[my:type]) WHERE nodeSet1.id IS NOT NULL"));
+ isSql("SELECT * FROM [my:type] JOIN [nt:base] as nodeSet1 ON
ISDESCENDANTNODE(nodeSet1,[my:type]) WHERE nodeSet1.id IS NOT NULL"));
}
@Test
public void
shouldTranslateFromXPathContainingPredicatesIdentifyingPropertiesThatMustHaveValues() {
+
assertThat(xpath("/jcr:root/testroot/serializationNode[@jcr:primaryType]"),
+ isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) =
'/testroot/serializationNode' AND nodeSet1.[jcr:primaryType] IS NOT NULL"));
assertThat(xpath("//element(*,my:type)[@id]"), isSql("SELECT *
FROM [my:type] WHERE id IS NOT NULL"));
assertThat(xpath("//element(*,my:type)[@id][@name]"),
isSql("SELECT * FROM [my:type] WHERE id IS NOT NULL AND name IS
NOT NULL"));
@@ -191,8 +192,8 @@
assertThat(xpath("//element(*,my:type)/(@id union @name)"),
isSql("SELECT id, name FROM [my:type]"));
assertThat(xpath("//element(*,my:type)/(@id union @name union
@x:address)"),
isSql("SELECT id, name, [x:address] FROM [my:type]"));
- assertThat(xpath("//(@id|@name)"), isSql("SELECT nodeSet1.id,
nodeSet1.name FROM __ALLNODES__ AS nodeSet1"));
- assertThat(xpath("//./(@id|@name)"), isSql("SELECT nodeSet1.id,
nodeSet1.name FROM __ALLNODES__ AS nodeSet1"));
+ assertThat(xpath("//(@id|@name)"), isSql("SELECT nodeSet1.id,
nodeSet1.name FROM [nt:base] AS nodeSet1"));
+ assertThat(xpath("//./(@id|@name)"), isSql("SELECT nodeSet1.id,
nodeSet1.name FROM [nt:base] AS nodeSet1"));
}
@Test
@@ -207,68 +208,64 @@
@Test
public void shouldTranslateFromXPathOfAnyNodeWithName() {
- assertThat(xpath("//element(nodeName,*)"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE
NAME(nodeSet1) = 'nodeName'"));
+ assertThat(xpath("//element(nodeName,*)"), isSql("SELECT * FROM
[nt:base] AS nodeSet1 WHERE NAME(nodeSet1) = 'nodeName'"));
- assertThat(xpath("//element(nodeName,*)"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE
NAME(nodeSet1) = 'nodeName'"));
+ assertThat(xpath("//element(nodeName,*)"), isSql("SELECT * FROM
[nt:base] AS nodeSet1 WHERE NAME(nodeSet1) = 'nodeName'"));
- assertThat(xpath("//nodeName"), isSql("SELECT * FROM __ALLNODES__
AS nodeSet1 WHERE NAME(nodeSet1) = 'nodeName'"));
+ assertThat(xpath("//nodeName"), isSql("SELECT * FROM [nt:base] AS
nodeSet1 WHERE NAME(nodeSet1) = 'nodeName'"));
assertThat(xpath("/jcr:root//element(nodeName,*)"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE
NAME(nodeSet1) = 'nodeName'"));
+ isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE NAME(nodeSet1) =
'nodeName'"));
- assertThat(xpath("/jcr:root//nodeName"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE
NAME(nodeSet1) = 'nodeName'"));
+ assertThat(xpath("/jcr:root//nodeName"), isSql("SELECT * FROM
[nt:base] AS nodeSet1 WHERE NAME(nodeSet1) = 'nodeName'"));
}
@Test
public void shouldTranslateFromXPathOfNodeWithNameUnderRoot() {
assertThat(xpath("/jcr:root/element(nodeName,*)"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE
NAME(nodeSet1) = 'nodeName' AND DEPTH(nodeSet1) = CAST(1 AS LONG)"));
+ isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE NAME(nodeSet1) =
'nodeName' AND DEPTH(nodeSet1) = CAST(1 AS LONG)"));
- assertThat(xpath("/jcr:root/nodeName"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE
PATH(nodeSet1) = '/nodeName'"));
+ assertThat(xpath("/jcr:root/nodeName"), isSql("SELECT * FROM
[nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/nodeName'"));
- assertThat(xpath("nodeName"), isSql("SELECT * FROM __ALLNODES__ AS
nodeSet1 WHERE PATH(nodeSet1) = '/nodeName'"));
+ assertThat(xpath("nodeName"), isSql("SELECT * FROM [nt:base] AS
nodeSet1 WHERE PATH(nodeSet1) = '/nodeName'"));
}
@Test
public void shouldTranslateFromXPathOfAnyNodeUsingPredicate() {
assertThat(xpath("//.[jcr:contains(.,'bar')]"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE
CONTAINS(nodeSet1.*,'bar')"));
+ isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE
CONTAINS(nodeSet1.*,'bar')"));
assertThat(xpath("//.[jcr:contains(a,'bar')]"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 JOIN __ALLNODES__
AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE
CONTAINS(nodeSet2.*,'bar')"));
+ isSql("SELECT * FROM [nt:base] AS nodeSet1 JOIN [nt:base] AS
nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE
CONTAINS(nodeSet2.*,'bar')"));
assertThat(xpath("//*[jcr:contains(.,'bar')]"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE
CONTAINS(nodeSet1.*,'bar')"));
+ isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE
CONTAINS(nodeSet1.*,'bar')"));
assertThat(xpath("//*[jcr:contains(a,'bar')]"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 JOIN __ALLNODES__
AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE
CONTAINS(nodeSet2.*,'bar')"));
+ isSql("SELECT * FROM [nt:base] AS nodeSet1 JOIN [nt:base] AS
nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE
CONTAINS(nodeSet2.*,'bar')"));
assertThat(xpath("//*[jcr:contains(a/@b,'bar')]"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 JOIN __ALLNODES__
AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE NAME(nodeSet2) = 'a' AND
CONTAINS(nodeSet2.b,'bar')"));
+ isSql("SELECT * FROM [nt:base] AS nodeSet1 JOIN [nt:base] AS
nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE NAME(nodeSet2) = 'a' AND
CONTAINS(nodeSet2.b,'bar')"));
assertThat(xpath("//*[jcr:contains(a/*/@b,'bar')]"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 JOIN __ALLNODES__
AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) JOIN __ALLNODES__ AS nodeSet3 ON
ISCHILDNODE(nodeSet3,nodeSet2) WHERE NAME(nodeSet2) = 'a' AND
CONTAINS(nodeSet3.b,'bar')"));
+ isSql("SELECT * FROM [nt:base] AS nodeSet1 JOIN [nt:base] AS
nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) JOIN [nt:base] AS nodeSet3 ON
ISCHILDNODE(nodeSet3,nodeSet2) WHERE NAME(nodeSet2) = 'a' AND
CONTAINS(nodeSet3.b,'bar')"));
assertThat(xpath("/jcr:root//element(*)[jcr:contains(a/@b,'bar')]"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 JOIN __ALLNODES__
AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE NAME(nodeSet2) = 'a' AND
CONTAINS(nodeSet2.b,'bar')"));
+ isSql("SELECT * FROM [nt:base] AS nodeSet1 JOIN [nt:base] AS
nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE NAME(nodeSet2) = 'a' AND
CONTAINS(nodeSet2.b,'bar')"));
assertThat(xpath("/jcr:root//element(*)[jcr:contains(a/*/@b,'bar')]"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 JOIN __ALLNODES__
AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) JOIN __ALLNODES__ AS nodeSet3 ON
ISCHILDNODE(nodeSet3,nodeSet2) WHERE NAME(nodeSet2) = 'a' AND
CONTAINS(nodeSet3.b,'bar')"));
+ isSql("SELECT * FROM [nt:base] AS nodeSet1 JOIN [nt:base] AS
nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) JOIN [nt:base] AS nodeSet3 ON
ISCHILDNODE(nodeSet3,nodeSet2) WHERE NAME(nodeSet2) = 'a' AND
CONTAINS(nodeSet3.b,'bar')"));
assertThat(xpath("/jcr:root//*[jcr:contains(a/@b,'bar')]"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 JOIN __ALLNODES__
AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE NAME(nodeSet2) = 'a' AND
CONTAINS(nodeSet2.b,'bar')"));
+ isSql("SELECT * FROM [nt:base] AS nodeSet1 JOIN [nt:base] AS
nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE NAME(nodeSet2) = 'a' AND
CONTAINS(nodeSet2.b,'bar')"));
assertThat(xpath("/jcr:root//*[jcr:contains(a/*/@b,'bar')]"),
- isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 JOIN __ALLNODES__
AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) JOIN __ALLNODES__ AS nodeSet3 ON
ISCHILDNODE(nodeSet3,nodeSet2) WHERE NAME(nodeSet2) = 'a' AND
CONTAINS(nodeSet3.b,'bar')"));
+ isSql("SELECT * FROM [nt:base] AS nodeSet1 JOIN [nt:base] AS
nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) JOIN [nt:base] AS nodeSet3 ON
ISCHILDNODE(nodeSet3,nodeSet2) WHERE NAME(nodeSet2) = 'a' AND
CONTAINS(nodeSet3.b,'bar')"));
}
- // @Test
- // public void shouldParseXPathExpressions() {
- // assertParsable("/jcr:root/a/b/c");
- // assertParsable("/jcr:root/a/b/c[*]");
- // assertParsable("/jcr:root/some[1]/element(nodes, my:type)[1]");
- // assertParsable("//element(*,my:type)");
- // assertParsable("//element(*,my:type)[@jcr:title='something' and
@globalProperty='something else']");
- // assertParsable("//element(*,my:type)[@jcr:title | @globalProperty]");
- // assertParsable("//element(*, my:type) order by @my:title");
- // assertParsable("//element(*, my:type) [jcr:contains(., 'jcr')] order
by jcr:score() descending");
- // assertParsable("//element(*, employee)[@secretary and @assistant]");
- // }
+ @Test
+ public void shouldParseXPathExpressions() {
+ xpath("/jcr:root/a/b/c");
+ xpath("/jcr:root/a/b/c[*]");
+ xpath("/jcr:root/some[1]/element(nodes, my:type)[1]");
+ xpath("//element(*,my:type)");
+ xpath("//element(*,my:type)[@jcr:title='something' and
@globalProperty='something else']");
+ xpath("//element(*,my:type)[@jcr:title | @globalProperty]");
+ xpath("//element(*, my:type) order by @my:title");
+ xpath("//element(*, my:type) [jcr:contains(., 'jcr')] order by
jcr:score() descending");
+ xpath("//element(*, employee)[@secretary and @assistant]");
+ }
//
----------------------------------------------------------------------------------------------------------------
// utility methods
Modified: trunk/dna-jcr/src/test/resources/tck/repositoryForTckTests.xml
===================================================================
--- trunk/dna-jcr/src/test/resources/tck/repositoryForTckTests.xml 2009-12-31 18:53:06 UTC
(rev 1507)
+++ trunk/dna-jcr/src/test/resources/tck/repositoryForTckTests.xml 2009-12-31 21:36:01 UTC
(rev 1508)
@@ -49,4 +49,13 @@
Cannot test \r character here on Windows as TCK XML Parser will replace it with \n
and fail the comparison
-->
<nt:unstructured jcr:name="node4"
multi-line-property="Line	1
Line 2"/>
+ <!--
+ XPathPosIndexTest requires multiple nodes named 'node1'
+ -->
+ <nt:unstructured jcr:name="node1"
prop1="<foo&foo>">
+ <nt:unstructured jcr:name="jcr:xmltext" jcr:xmlcharacters="This
is the text for node1[2]!" />
+ </nt:unstructured>
+ <nt:unstructured jcr:name="node1"
prop1="<foo&foo>">
+ <nt:unstructured jcr:name="jcr:xmltext" jcr:xmlcharacters="This
is the text for node1[3]!" />
+ </nt:unstructured>
</testroot>
\ No newline at end of file
Modified:
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/AbstractLuceneSearchEngine.java
===================================================================
---
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/AbstractLuceneSearchEngine.java 2009-12-31
18:53:06 UTC (rev 1507)
+++
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/AbstractLuceneSearchEngine.java 2009-12-31
21:36:01 UTC (rev 1508)
@@ -25,6 +25,7 @@
import java.io.IOException;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
@@ -87,7 +88,6 @@
import org.jboss.dna.graph.query.model.PropertyExistence;
import org.jboss.dna.graph.query.model.PropertyValue;
import org.jboss.dna.graph.query.model.SameNode;
-import org.jboss.dna.graph.query.model.SelectorName;
import org.jboss.dna.graph.query.model.SetCriteria;
import org.jboss.dna.graph.query.model.StaticOperand;
import org.jboss.dna.graph.query.model.TypeSystem;
@@ -103,6 +103,8 @@
import org.jboss.dna.graph.search.SearchEngine;
import org.jboss.dna.graph.search.SearchEngineProcessor;
import org.jboss.dna.graph.search.SearchEngineWorkspace;
+import org.jboss.dna.search.lucene.query.HasValueQuery;
+import org.jboss.dna.search.lucene.query.MatchNoneQuery;
/**
* An abstract {@link SearchEngine} implementation that is set up to use the Lucene
library. This provides an abstract
@@ -349,11 +351,22 @@
Query pushDownQuery = null;
Constraint postProcessConstraint = null;
try {
+ QueryFactory queryFactory = null;
for (Constraint andedConstraint : request.andedConstraints()) {
// Determine if it can be represented as a Lucene query ...
assert andedConstraint != null;
- Query constraintQuery = queryFactory(session,
request.variables()).createQuery(andedConstraint);
+ if (queryFactory == null) queryFactory = queryFactory(session,
request.variables());
+ Query constraintQuery = queryFactory.createQuery(andedConstraint);
if (constraintQuery != null) {
+ if (constraintQuery instanceof MatchAllDocsQuery) {
+ // This constraint includes all values, so we can just skip
it ...
+ continue;
+ }
+ if (constraintQuery instanceof MatchNoneQuery) {
+ // This constraint invalidates all of the other AND-ed
constraints ...
+ pushDownQuery = constraintQuery;
+ break;
+ }
// The AND-ed constraint _can_ be represented as a push-down
Lucene query ...
if (pushDownQuery == null) {
// This must be the first query ...
@@ -398,47 +411,54 @@
// Get the results from Lucene ...
List<Object[]> tuples = null;
final Columns columns = request.resultColumns();
- try {
- // Execute the query against the content indexes ...
- IndexSearcher searcher = session.getContentSearcher();
- TupleCollector collector = session.createTupleCollector(columns);
- searcher.search(pushDownQuery, collector);
- tuples = collector.getTuples();
- } catch (IOException e) {
- // There was a problem executing the Lucene query ...
- request.setError(e);
- return;
+ if (pushDownQuery instanceof MatchNoneQuery) {
+ // There are no results ...
+ tuples = Collections.emptyList();
+ } else {
+ try {
+ // Execute the query against the content indexes ...
+ IndexSearcher searcher = session.getContentSearcher();
+ TupleCollector collector = session.createTupleCollector(columns);
+ searcher.search(pushDownQuery, collector);
+ tuples = collector.getTuples();
+ } catch (IOException e) {
+ // There was a problem executing the Lucene query ...
+ request.setError(e);
+ return;
+ }
}
- if (postProcessConstraint != null && !tuples.isEmpty()) {
- // Create a delegate processing component that will return the tuples
we've already found ...
- final List<Object[]> allTuples = tuples;
- QueryContext queryContext = new QueryContext(request.schemata(),
typeSystem, null, new SimpleProblems(),
- request.variables());
- ProcessingComponent tuplesProcessor = new
ProcessingComponent(queryContext, columns) {
- @Override
- public List<Object[]> execute() {
- return allTuples;
- }
- };
- // Create a processing component that will apply these constraints to the
tuples we already found ...
- SelectComponent selector = new SelectComponent(tuplesProcessor,
postProcessConstraint, request.variables());
- tuples = selector.execute();
- }
+ if (!tuples.isEmpty()) {
+ if (postProcessConstraint != null) {
+ // Create a delegate processing component that will return the tuples
we've already found ...
+ final List<Object[]> allTuples = tuples;
+ QueryContext queryContext = new QueryContext(request.schemata(),
typeSystem, null, new SimpleProblems(),
+ request.variables());
+ ProcessingComponent tuplesProcessor = new
ProcessingComponent(queryContext, columns) {
+ @Override
+ public List<Object[]> execute() {
+ return allTuples;
+ }
+ };
+ // Create a processing component that will apply these constraints to
the tuples we already found ...
+ SelectComponent selector = new SelectComponent(tuplesProcessor,
postProcessConstraint, request.variables());
+ tuples = selector.execute();
+ }
- // Limit the tuples ...
- Limit limit = request.limit();
- if (!limit.isUnlimited()) {
- int firstIndex = limit.getOffset();
- int maxRows = Math.min(tuples.size(), limit.getRowLimit());
- if (firstIndex > 0) {
- if (firstIndex > tuples.size()) {
- tuples.clear();
+ // Limit the tuples ...
+ Limit limit = request.limit();
+ if (!limit.isUnlimited()) {
+ int firstIndex = limit.getOffset();
+ int maxRows = Math.min(tuples.size(), limit.getRowLimit());
+ if (firstIndex > 0) {
+ if (firstIndex > tuples.size()) {
+ tuples.clear();
+ } else {
+ tuples = tuples.subList(firstIndex, maxRows);
+ }
} else {
- tuples = tuples.subList(firstIndex, maxRows);
+ tuples = tuples.subList(0, maxRows);
}
- } else {
- tuples = tuples.subList(0, maxRows);
}
}
@@ -518,7 +538,7 @@
}
if (constraint instanceof PropertyExistence) {
PropertyExistence existence = (PropertyExistence)constraint;
- return createQuery(existence.getSelectorName(),
existence.getPropertyName());
+ return createQuery(existence);
}
if (constraint instanceof Between) {
Between between = (Between)constraint;
@@ -680,10 +700,13 @@
return valueFactory.create(stringFactory.create(value).toLowerCase());
}
- public Query createQuery( SelectorName selectorName,
- String propertyName ) {
- Term term = new Term(fieldNameFor(propertyName));
- return new TermQuery(term);
+ public Query createQuery( PropertyExistence existence ) {
+ String propertyName = existence.getPropertyName();
+ if ("jcr:primaryType".equals(propertyName)) {
+ // All nodes have a primary type, so therefore we can match all
documents ...
+ return new MatchAllDocsQuery();
+ }
+ return new HasValueQuery(fieldNameFor(propertyName));
}
public Query createQuery( String fieldName,
Added:
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/query/HasValueQuery.java
===================================================================
---
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/query/HasValueQuery.java
(rev 0)
+++
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/query/HasValueQuery.java 2009-12-31
21:36:01 UTC (rev 1508)
@@ -0,0 +1,259 @@
+/*
+ * JBoss DNA (
http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.search.lucene.query;
+
+import java.io.IOException;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.FieldSelector;
+import org.apache.lucene.document.FieldSelectorResult;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.search.Searcher;
+import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.Weight;
+
+/**
+ * A Lucene {@link Query} implementation that is satisfied if there is at least one value
for a document.
+ */
+public class HasValueQuery extends Query {
+
+ private static final long serialVersionUID = 1L;
+
+ protected final String fieldName;
+ protected final FieldSelector fieldSelector;
+
+ /**
+ * Construct a {@link Query} implementation that scores nodes according to the
supplied comparator.
+ *
+ * @param fieldName the name of the document field containing the value; may not be
null
+ */
+ public HasValueQuery( final String fieldName ) {
+ this.fieldName = fieldName;
+ this.fieldSelector = new FieldSelector() {
+ private static final long serialVersionUID = 1L;
+
+ public FieldSelectorResult accept( String fieldName ) {
+ return HasValueQuery.this.fieldName.equals(fieldName) ?
FieldSelectorResult.LOAD_AND_BREAK : FieldSelectorResult.NO_LOAD;
+ }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.lucene.search.Query#clone()
+ */
+ @Override
+ public Object clone() {
+ return new HasValueQuery(fieldName);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.apache.lucene.search.Query#createWeight(org.apache.lucene.search.Searcher)
+ */
+ @Override
+ public Weight createWeight( Searcher searcher ) {
+ return new ExistsWeight(searcher);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.lucene.search.Query#toString(java.lang.String)
+ */
+ @Override
+ public String toString( String field ) {
+ return fieldName + " exists";
+ }
+
+ protected boolean hasValue( IndexReader reader,
+ int docId ) throws IOException {
+ Document doc = reader.document(docId, fieldSelector);
+ String valueString = doc.get(fieldName);
+ return valueString != null;
+ }
+
+ /**
+ * Calculates query weights and builds query scores for our NOT queries.
+ */
+ protected class ExistsWeight extends Weight {
+ private static final long serialVersionUID = 1L;
+ private final Searcher searcher;
+
+ protected ExistsWeight( Searcher searcher ) {
+ this.searcher = searcher;
+ assert this.searcher != null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.lucene.search.Weight#getQuery()
+ */
+ @Override
+ public Query getQuery() {
+ return HasValueQuery.this;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This implementation always returns a weight factor of 1.0.
+ * </p>
+ *
+ * @see org.apache.lucene.search.Weight#getValue()
+ */
+ @Override
+ public float getValue() {
+ return 1.0f; // weight factor of 1.0
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This implementation always returns a normalization factor of 1.0.
+ * </p>
+ *
+ * @see org.apache.lucene.search.Weight#sumOfSquaredWeights()
+ */
+ @Override
+ public float sumOfSquaredWeights() {
+ return 1.0f; // normalization factor of 1.0
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This implementation always does nothing, as there is nothing to normalize.
+ * </p>
+ *
+ * @see org.apache.lucene.search.Weight#normalize(float)
+ */
+ @Override
+ public void normalize( float norm ) {
+ // No need to do anything here
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.apache.lucene.search.Weight#scorer(org.apache.lucene.index.IndexReader, boolean,
boolean)
+ */
+ @Override
+ public Scorer scorer( IndexReader reader,
+ boolean scoreDocsInOrder,
+ boolean topScorer ) {
+ // Return a custom scorer ...
+ return new ExistsScorer(reader);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.apache.lucene.search.Weight#explain(org.apache.lucene.index.IndexReader, int)
+ */
+ @Override
+ public Explanation explain( IndexReader reader,
+ int doc ) {
+ return new Explanation(getValue(), getQuery().toString());
+ }
+ }
+
+ /**
+ * A scorer for the Path query.
+ */
+ protected class ExistsScorer extends Scorer {
+ private int docId = -1;
+ private final int maxDocId;
+ private final IndexReader reader;
+
+ protected ExistsScorer( IndexReader reader ) {
+ // We don't care which Similarity we have, because we don't use it.
So get the default.
+ super(Similarity.getDefault());
+ this.reader = reader;
+ assert this.reader != null;
+ this.maxDocId = this.reader.maxDoc() - 1;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.lucene.search.DocIdSetIterator#docID()
+ */
+ @Override
+ public int docID() {
+ return docId;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.lucene.search.DocIdSetIterator#nextDoc()
+ */
+ @Override
+ public int nextDoc() throws IOException {
+ do {
+ ++docId;
+ if (reader.isDeleted(docId)) {
+ // We should skip this document ...
+ continue;
+ }
+ if (hasValue(reader, docId)) return docId;
+ } while (docId < maxDocId);
+ return Scorer.NO_MORE_DOCS;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.apache.lucene.search.DocIdSetIterator#advance(int)
+ */
+ @Override
+ public int advance( int target ) throws IOException {
+ if (target == Scorer.NO_MORE_DOCS) return target;
+ while (true) {
+ int doc = nextDoc();
+ if (doc >= target) return doc;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This method always returns a score of 1.0 for the current document, since only
those documents that satisfy the NOT are
+ * scored by this scorer.
+ * </p>
+ *
+ * @see org.apache.lucene.search.Scorer#score()
+ */
+ @Override
+ public float score() {
+ return 1.0f;
+ }
+ }
+}
Property changes on:
trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/query/HasValueQuery.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified:
trunk/extensions/dna-search-lucene/src/test/java/org/jboss/dna/search/lucene/LuceneSearchEngineTest.java
===================================================================
---
trunk/extensions/dna-search-lucene/src/test/java/org/jboss/dna/search/lucene/LuceneSearchEngineTest.java 2009-12-31
18:53:06 UTC (rev 1507)
+++
trunk/extensions/dna-search-lucene/src/test/java/org/jboss/dna/search/lucene/LuceneSearchEngineTest.java 2009-12-31
21:36:01 UTC (rev 1508)
@@ -373,6 +373,14 @@
//
----------------------------------------------------------------------------------------------------------------
@Test
+ public void shouldFindAllNodesBySimpleQuery() {
+ indexWorkspace(workspaceName1);
+ String query = "SELECT [jcr:primaryType] FROM __ALLNODES__";
+ QueryResults results = query(workspaceName1, query);
+ assertRowCount(results, 18);
+ }
+
+ @Test
public void shouldFindNodesBySimpleQuery() {
indexWorkspace(workspaceName1);
String query = "SELECT model, maker FROM __ALLNODES__";