Index: jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/PathQueryNodeTest.java =================================================================== --- jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/PathQueryNodeTest.java (revision 563919) +++ jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/PathQueryNodeTest.java (working copy) @@ -26,21 +26,23 @@ private static final NamespaceResolver JCR_RESOLVER = new NamespaceResolver() { public String getJCRName(QName qName) { - return this.getPrefix(qName.getNamespaceURI()) + ":" - + qName.getLocalName(); + throw new UnsupportedOperationException(); } public String getPrefix(String uri) { - return QName.NS_JCR_PREFIX; + throw new UnsupportedOperationException(); } public QName getQName(String jcrName) { - return new QName(QName.NS_JCR_URI, - jcrName.substring(jcrName.indexOf(':'))); + throw new UnsupportedOperationException(); } public String getURI(String prefix) { - return QName.NS_JCR_URI; + if (QName.NS_JCR_PREFIX.equals(prefix)) + return QName.NS_JCR_URI; + if (QName.NS_NT_PREFIX.equals(prefix)) + return QName.NS_NT_URI; + return ""; } }; @@ -64,4 +66,15 @@ assertTrue(queryRootNode.needsSystemTree()); } + public void testNeedsSystemTreeForAllNodesByNodeType() throws Exception { + QueryRootNode queryRootNode = XPathQueryBuilder.createQuery("//element(*, nt:resource)", JCR_RESOLVER); + assertFalse(queryRootNode.needsSystemTree()); + + queryRootNode = XPathQueryBuilder.createQuery("//element(*, nt:resource)[@jcr:test = 'foo']", JCR_RESOLVER); + assertFalse(queryRootNode.needsSystemTree()); + + queryRootNode = XPathQueryBuilder.createQuery("//element(*, nt:nodeType)", JCR_RESOLVER); + assertTrue(queryRootNode.needsSystemTree()); + } + } Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/PathQueryNode.java =================================================================== --- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/PathQueryNode.java (revision 563919) +++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/PathQueryNode.java (working copy) @@ -16,6 +16,9 @@ */ package org.apache.jackrabbit.core.query; +import java.util.Arrays; +import java.util.List; + import org.apache.jackrabbit.name.QName; /** @@ -23,6 +26,23 @@ */ public class PathQueryNode extends NAryQueryNode { + private static final List VALID_SYSTEM_INDEX_NODE_TYPE_NAMES = Arrays.asList(new QName[] { + QName.NT_CHILDNODEDEFINITION, + QName.NT_FROZENNODE, + QName.NT_NODETYPE, + QName.NT_PROPERTYDEFINITION, + QName.NT_VERSION, + QName.NT_VERSIONEDCHILD, + QName.NT_VERSIONHISTORY, + QName.NT_VERSIONLABELS, + QName.REP_NODETYPES, + QName.REP_SYSTEM, + QName.REP_VERSIONSTORAGE, + // Supertypes + QName.NT_BASE, + QName.MIX_REFERENCEABLE + }); + /** * Flag indicating whether this path is absolute. */ @@ -125,10 +145,23 @@ } QName firstPathStepName = pathSteps[0].getNameTest(); - // If the first location step has a null name test we need to include - // the system tree ("*") - if (firstPathStepName == null) + if (firstPathStepName == null) { + // If the first operand of the path steps is a node type query + // we do not need to include the system index if the node type is + // none of the node types that may occur in the system index. + QueryNode[] pathStepOperands = pathSteps[0].getOperands(); + if (pathStepOperands.length > 0) { + if (pathStepOperands[0] instanceof NodeTypeQueryNode) { + NodeTypeQueryNode nodeTypeQueryNode = (NodeTypeQueryNode) pathStepOperands[0]; + if (!VALID_SYSTEM_INDEX_NODE_TYPE_NAMES.contains(nodeTypeQueryNode.getValue())) { + return false; + } + } + } + // If the first location step has a null name test we need to include + // the system tree ("*") return true; + } // Calculate the first workspace relative location step LocationStepQueryNode firstWorkspaceRelativeStep = pathSteps[0];