Return-Path: Delivered-To: apmail-incubator-jackrabbit-commits-archive@www.apache.org Received: (qmail 80971 invoked from network); 10 Mar 2005 09:57:17 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur-2.apache.org with SMTP; 10 Mar 2005 09:57:17 -0000 Received: (qmail 17524 invoked by uid 500); 10 Mar 2005 09:57:16 -0000 Mailing-List: contact jackrabbit-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: jackrabbit-dev@incubator.apache.org Delivered-To: mailing list jackrabbit-commits@incubator.apache.org Received: (qmail 17508 invoked by uid 500); 10 Mar 2005 09:57:16 -0000 Delivered-To: apmail-incubator-jackrabbit-cvs@incubator.apache.org Received: (qmail 17502 invoked by uid 99); 10 Mar 2005 09:57:16 -0000 X-ASF-Spam-Status: No, hits=-9.8 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from minotaur.apache.org (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.28) with SMTP; Thu, 10 Mar 2005 01:57:15 -0800 Received: (qmail 80943 invoked by uid 65534); 10 Mar 2005 09:57:14 -0000 Message-ID: <20050310095714.80941.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Mailer: svnmailer-1.0.0-dev Date: Thu, 10 Mar 2005 09:57:13 -0000 Subject: svn commit: r156923 - in incubator/jackrabbit/trunk/src: java/org/apache/jackrabbit/core/search/ java/org/apache/jackrabbit/core/search/lucene/ java/org/apache/jackrabbit/core/search/sql/ java/org/apache/jackrabbit/core/search/xpath/ test/org/apache/jackrabbit/core/search/ test/org/apache/jackrabbit/test/api/query/ To: jackrabbit-cvs@incubator.apache.org From: mreutegg@apache.org X-Virus-Checked: Checked X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N Author: mreutegg Date: Thu Mar 10 01:57:09 2005 New Revision: 156923 URL: http://svn.apache.org/viewcvs?view=3Drev&rev=3D156923 Log: Implement location step with context position index. Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/A= bstractQueryHandler.java incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/L= ocationStepQueryNode.java incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/Q= ueryConstants.java incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/R= elationQueryNode.java incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/l= ucene/ChildAxisQuery.java incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/l= ucene/LuceneQueryBuilder.java incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/l= ucene/QueryImpl.java incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/s= ql/JCRSQLQueryBuilder.java incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/s= ql/QueryFormat.java incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/x= path/QueryFormat.java incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/x= path/XPathQueryBuilder.java incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/core/search/S= electClauseTest.java incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/core/search/X= PathAxisTest.java incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/quer= y/XPathDocOrderTest.java Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/se= arch/AbstractQueryHandler.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/= apache/jackrabbit/core/search/AbstractQueryHandler.java?view=3Ddiff&r1=3D15= 6922&r2=3D156923 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/A= bstractQueryHandler.java (original) +++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/A= bstractQueryHandler.java Thu Mar 10 01:57:09 2005 @@ -81,7 +81,7 @@ * @return the persistent ItemStateProvider of the current * workspace. */ - protected ItemStateManager getItemStateProvider() { + public ItemStateManager getItemStateProvider() { return stateProvider; } =20 Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/se= arch/LocationStepQueryNode.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/= apache/jackrabbit/core/search/LocationStepQueryNode.java?view=3Ddiff&r1=3D1= 56922&r2=3D156923 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/L= ocationStepQueryNode.java (original) +++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/L= ocationStepQueryNode.java Thu Mar 10 01:57:09 2005 @@ -30,6 +30,12 @@ */ public class LocationStepQueryNode extends NAryQueryNode { =20 + /** Constant value for position index =3D last() */ + public static final int LAST =3D Integer.MIN_VALUE; + + /** Constant value to indicate no position index */ + public static final int NONE =3D Integer.MIN_VALUE + 1; + /** Empty QueryNode array for us as return value */ private static final QueryNode[] EMPTY =3D new QueryNode[0]; =20 @@ -46,10 +52,9 @@ private boolean includeDescendants; =20 /** - * If index is larger than 0 this location step contains - * a position index. + * The context position index. Initially {@link #NONE}. */ - private int index =3D 0; + private int index =3D NONE; =20 /** * Creates a new LocationStepQueryNode with a reference to @@ -111,9 +116,8 @@ } =20 /** - * Returns the predicate nodes for this location step. This method will - * not return a position predicate. Use {@link #getIndex} to retrieve - * this information. + * Returns the predicate nodes for this location step. This method may + * also return a position predicate. * @return the predicate nodes or an empty array if there are no predi= cates * for this location step. */ @@ -126,21 +130,17 @@ } =20 /** - * Sets the position index for this step. A value of 0 (zero) indicates + * Sets the position index for this step. A value of {@link #NONE} ind= icates * that this location step has no position index assigned. That is, the * step selects all same name siblings. * @param index the position index. - * @exception IllegalArgumentException if index < 0. */ public void setIndex(int index) { - if (index < 0) { - throw new IllegalArgumentException("index < 0"); - } this.index =3D index; } =20 /** - * Returns the position index for this step. A value of 0 (zero) indic= ates + * Returns the position index for this step. A value of {@link #NONE} = indicates * that this location step has no position index assigned. That is, the * step selects all same name siblings. * @return the position index for this step. Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/se= arch/QueryConstants.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/= apache/jackrabbit/core/search/QueryConstants.java?view=3Ddiff&r1=3D156922&r= 2=3D156923 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/Q= ueryConstants.java (original) +++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/Q= ueryConstants.java Thu Mar 10 01:57:09 2005 @@ -70,6 +70,11 @@ */ public static int TYPE_TIMESTAMP =3D 5; =20 + /** + * position index type + */ + public static int TYPE_POSITION =3D 6; + public static int OPERATIONS =3D 10; =20 /** Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/se= arch/RelationQueryNode.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/= apache/jackrabbit/core/search/RelationQueryNode.java?view=3Ddiff&r1=3D15692= 2&r2=3D156923 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/R= elationQueryNode.java (original) +++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/R= elationQueryNode.java Thu Mar 10 01:57:09 2005 @@ -37,6 +37,11 @@ private long valueLong; =20 /** + * The int value of the position index. + */ + private int valuePosition; + + /** * The double value of the relation if this is a query is= of * type double */ @@ -62,7 +67,7 @@ =20 /** * The value type of this relation. One of {@link #TYPE_DATE}, {@link - * #TYPE_DOUBLE}, {@link #TYPE_LONG}, {@link #TYPE_STRING}. + * #TYPE_DOUBLE}, {@link #TYPE_LONG}, {@link #TYPE_STRING}, {@link #TY= PE_POSITION}. */ private int type; =20 @@ -206,6 +211,25 @@ public void setLongValue(long value) { valueLong =3D value; type =3D TYPE_LONG; + } + + /** + * Returns the int position index value if this relation = is + * of type {@link #TYPE_POSITION}. + * @return the position index value. + */ + public int getPositionValue() { + return valuePosition; + } + + /** + * Sets a new value for the position index. + * + * @param value the new value. + */ + public void setPositionValue(int value) { + valuePosition =3D value; + type =3D TYPE_POSITION; } =20 /** Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/se= arch/lucene/ChildAxisQuery.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/= apache/jackrabbit/core/search/lucene/ChildAxisQuery.java?view=3Ddiff&r1=3D1= 56922&r2=3D156923 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/l= ucene/ChildAxisQuery.java (original) +++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/l= ucene/ChildAxisQuery.java Thu Mar 10 01:57:09 2005 @@ -26,6 +26,14 @@ import org.apache.lucene.search.Searcher; import org.apache.lucene.search.Similarity; import org.apache.lucene.search.Weight; +import org.apache.lucene.search.TermQuery; +import org.apache.lucene.document.Document; +import org.apache.jackrabbit.core.state.ItemStateManager; +import org.apache.jackrabbit.core.state.NodeState; +import org.apache.jackrabbit.core.state.ItemStateException; +import org.apache.jackrabbit.core.NodeId; +import org.apache.jackrabbit.core.QName; +import org.apache.jackrabbit.core.search.LocationStepQueryNode; =20 import java.io.IOException; import java.util.ArrayList; @@ -40,23 +48,67 @@ class ChildAxisQuery extends Query { =20 /** + * The item state manager containing persistent item states. + */ + private final ItemStateManager itemMgr; + + /** * The context query */ private final Query contextQuery; =20 /** + * The nameTest to apply on the child axis, or null if all + * child nodes should be selected. + */ + private final String nameTest; + + /** + * The context position for the selected child node, or + * {@link LocationStepQueryNode#NONE} if no position is specified. + */ + private final int position; + + /** * The scorer of the context query */ private Scorer contextScorer; =20 /** + * The scorer of the name test query + */ + private Scorer nameTestScorer; + + /** + * Creates a new ChildAxisQuery based on a context<= /code> + * query. + * + * @param itemMgr the item state manager. + * @param context the context for this query. + * @param nameTest a name test or null if any child node = is + * selected. + */ + ChildAxisQuery(ItemStateManager itemMgr, Query context, String nameTes= t) { + this(itemMgr, context, nameTest, LocationStepQueryNode.NONE); + } + + /** * Creates a new ChildAxisQuery based on a context<= /code> * query. * + * @param itemMgr the item state manager. * @param context the context for this query. + * @param nameTest a name test or null if any child node = is + * selected. + * @param position the context position of the child node to select. If + * position is {@link LocationStepQueryNode#NONE}, the co= ntext + * position of the child node is not checked. */ - ChildAxisQuery(Query context) { + ChildAxisQuery(ItemStateManager itemMgr, Query context, String nameTes= t, int position) { + this.itemMgr =3D itemMgr; this.contextQuery =3D context; + this.nameTest =3D nameTest; + this.position =3D position; } =20 /** @@ -142,6 +194,9 @@ */ public Scorer scorer(IndexReader reader) throws IOException { contextScorer =3D contextQuery.weight(searcher).scorer(reader); + if (nameTest !=3D null) { + nameTestScorer =3D new TermQuery(new Term(FieldNames.LABEL= , nameTest)).weight(searcher).scorer(reader); + } return new ChildAxisScorer(searcher.getSimilarity(), reader); } =20 @@ -256,17 +311,102 @@ // @todo maintain cache of doc id hierarchy hits.set(doc); } - }); // find all + }); + + // collect nameTest hits + final BitSet nameTestHits =3D new BitSet(); + if (nameTestScorer !=3D null) { + nameTestScorer.score(new HitCollector() { + public void collect(int doc, float score) { + nameTestHits.set(doc); + } + }); + } + + // read the uuids of the context nodes for (int i =3D hits.nextSetBit(0); i >=3D 0; i =3D hits.ne= xtSetBit(i + 1)) { String uuid =3D reader.document(i).get(FieldNames.UUID= ); uuids.add(uuid); } =20 + // collect the doc ids of all child nodes. we reuse the ex= isting + // bitset. hits.clear(); for (Iterator it =3D uuids.iterator(); it.hasNext();) { TermDocs children =3D reader.termDocs(new Term(FieldNa= mes.PARENT, (String) it.next())); while (children.next()) { hits.set(children.doc()); + } + } + // filter out the child nodes that do not match the name t= est + // if there is any name test at all. + if (nameTestScorer !=3D null) { + hits.and(nameTestHits); + } + + // filter by index + if (position !=3D LocationStepQueryNode.NONE) { + for (int i =3D hits.nextSetBit(0); i >=3D 0; i =3D hit= s=2EnextSetBit(i + 1)) { + Document node =3D reader.document(i); + String parentUUID =3D node.get(FieldNames.PARENT); + String uuid =3D node.get(FieldNames.UUID); + try { + NodeState state =3D (NodeState) itemMgr.getIte= mState(new NodeId(parentUUID)); + if (nameTest =3D=3D null) { + // only select this node if it is the chil= d at + // specified position + if (position =3D=3D LocationStepQueryNode.= LAST) { + // only select last + List childNodes =3D state.getChildNode= Entries(); + if (childNodes.size() =3D=3D 0 + || !((NodeState.ChildNodeEntry= ) childNodes.get(childNodes.size() - 1)).getUUID().equals(uuid)) { + hits.flip(i); + } + } else { + List childNodes =3D state.getChildNode= Entries(); + if (position < 1 + || childNodes.size() < position + || !((NodeState.ChildNodeEntry= ) childNodes.get(position - 1)).getUUID().equals(uuid)) { + hits.flip(i); + } + } + } else { + // select the node when its index is equal= to + // specified position + if (position =3D=3D LocationStepQueryNode.= LAST) { + // only select last + List childNodes =3D state.getChildNode= Entries(uuid); + if (childNodes.size() =3D=3D 0) { + // no such child node, probably de= leted meanwhile + hits.flip(i); + } else { + // only use the last one + QName name =3D ((NodeState.ChildNo= deEntry) childNodes.get(0)).getName(); + childNodes =3D state.getChildNodeE= ntries(name); + if (childNodes.size() =3D=3D 0 + || !((NodeState.ChildNodeE= ntry) childNodes.get(childNodes.size() - 1)).getUUID().equals(uuid)) { + hits.flip(i); + } + } + } else { + List childNodes =3D state.getChildNode= Entries(uuid); + if (childNodes.size() =3D=3D 0) { + // no such child node, probably ha= s been deleted meanwhile + hits.flip(i); + } else { + for (int j =3D 0; j < childNodes.s= ize(); j++) { + NodeState.ChildNodeEntry entry= =3D (NodeState.ChildNodeEntry) childNodes.get(j); + if (entry.getIndex() !=3D posi= tion) { + hits.flip(i); + } + } + } + } + } + } catch (ItemStateException e) { + // ignore this node, probably has been deleted= meanwhile + hits.flip(i); + } } } } Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/se= arch/lucene/LuceneQueryBuilder.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/= apache/jackrabbit/core/search/lucene/LuceneQueryBuilder.java?view=3Ddiff&r1= =3D156922&r2=3D156923 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/l= ucene/LuceneQueryBuilder.java (original) +++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/l= ucene/LuceneQueryBuilder.java Thu Mar 10 01:57:09 2005 @@ -24,6 +24,7 @@ import org.apache.jackrabbit.core.QName; import org.apache.jackrabbit.core.SessionImpl; import org.apache.jackrabbit.core.UnknownPrefixException; +import org.apache.jackrabbit.core.state.ItemStateManager; import org.apache.jackrabbit.core.search.AndQueryNode; import org.apache.jackrabbit.core.search.ExactQueryNode; import org.apache.jackrabbit.core.search.LocationStepQueryNode; @@ -38,6 +39,7 @@ import org.apache.jackrabbit.core.search.QueryRootNode; import org.apache.jackrabbit.core.search.RelationQueryNode; import org.apache.jackrabbit.core.search.TextsearchQueryNode; +import org.apache.jackrabbit.core.search.QueryNode; import org.apache.log4j.Logger; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.index.Term; @@ -90,6 +92,11 @@ private SessionImpl session; =20 /** + * The shared item state manager of the workspace. + */ + private ItemStateManager sharedItemMgr; + + /** * Namespace mappings to internal prefixes */ private NamespaceMappings nsMappings; @@ -114,17 +121,20 @@ * * @param root the root node of the abstract query tree. * @param session of the user executing this query. + * @param sharedItemMgr the shared item state manager of the workspace. * @param nsMappings namespace resolver for internal prefixes. * @param analyzer for parsing the query statement of the contains f= unction. * @param propReg the property type registry. */ private LuceneQueryBuilder(QueryRootNode root, SessionImpl session, + ItemStateManager sharedItemMgr, NamespaceMappings nsMappings, Analyzer analyzer, PropertyTypeRegistry propReg) { this.root =3D root; this.session =3D session; + this.sharedItemMgr =3D sharedItemMgr; this.nsMappings =3D nsMappings; this.analyzer =3D analyzer; this.propRegistry =3D propReg; @@ -136,6 +146,7 @@ * * @param root the root node of the abstract query tree. * @param session of the user executing the query. + * @param sharedItemMgr the shared item state manager of the workspace. * @param nsMappings namespace resolver for internal prefixes. * @param analyzer for parsing the query statement of the contains f= unction. * @param propReg the property type registry to lookup type informa= tion. @@ -144,13 +155,14 @@ */ public static Query createQuery(QueryRootNode root, SessionImpl session, + ItemStateManager sharedItemMgr, NamespaceMappings nsMappings, Analyzer analyzer, PropertyTypeRegistry propReg) throws RepositoryException { =20 - LuceneQueryBuilder builder =3D new LuceneQueryBuilder(root, - session, nsMappings, analyzer, propReg); + LuceneQueryBuilder builder =3D new LuceneQueryBuilder(root, sessio= n, + sharedItemMgr, nsMappings, analyzer, propReg); =20 Query q =3D builder.createLuceneQuery(); if (builder.exceptions.size() > 0) { @@ -385,6 +397,17 @@ andQuery.add((Query) predicates[i], true, false); } =20 + // check for position predicate + QueryNode[] pred =3D node.getPredicates(); + for (int i =3D 0; i < pred.length; i++) { + if (pred[i].getType() =3D=3D QueryNode.TYPE_RELATION) { + RelationQueryNode pos =3D (RelationQueryNode) pred[i]; + if (pos.getValueType() =3D=3D QueryConstants.TYPE_POSITION= ) { + node.setIndex(pos.getPositionValue()); + } + } + } + TermQuery nameTest =3D null; if (node.getNameTest() !=3D null) { try { @@ -408,19 +431,19 @@ andQuery =3D new BooleanQuery(); andQuery.add(subQuery, true, false); } else { - // @todo this will traverse the whole index, optimize! + // todo this will traverse the whole index, optimize! Query subQuery =3D new MatchAllQuery(FieldNames.UUID); context =3D new DescendantSelfAxisQuery(context, subQu= ery); - andQuery.add(new ChildAxisQuery(context), true, false); + andQuery.add(new ChildAxisQuery(sharedItemMgr, context= , null, node.getIndex()), true, false); } } } else { - // select child nodes - andQuery.add(new ChildAxisQuery(context), true, false); - // name test if (nameTest !=3D null) { - andQuery.add(nameTest, true, false); + andQuery.add(new ChildAxisQuery(sharedItemMgr, context, na= meTest.getTerm().text(), node.getIndex()), true, false); + } else { + // select child nodes + andQuery.add(new ChildAxisQuery(sharedItemMgr, context, nu= ll, node.getIndex()), true, false); } } =20 @@ -452,6 +475,9 @@ stringValues =3D getStringValues(node.getProperty(), n= ode.getStringValue()); } break; + case QueryConstants.TYPE_POSITION: + // ignore position. is handled in the location step + return null; default: throw new IllegalArgumentException("Unknown relation type:= " + node.getValueType()); Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/se= arch/lucene/QueryImpl.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/= apache/jackrabbit/core/search/lucene/QueryImpl.java?view=3Ddiff&r1=3D156922= &r2=3D156923 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/l= ucene/QueryImpl.java (original) +++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/l= ucene/QueryImpl.java Thu Mar 10 01:57:09 2005 @@ -115,8 +115,9 @@ */ public QueryResult execute() throws RepositoryException { // build lucene query - Query query =3D LuceneQueryBuilder.createQuery(root, - session, index.getNamespaceMappings(), index.getAnalyzer()= , propReg); + Query query =3D LuceneQueryBuilder.createQuery(root, session, + index.getItemStateProvider(), index.getNamespaceMappings()= ,=20 + index.getAnalyzer(), propReg); =20 OrderQueryNode orderNode =3D root.getOrderNode(); =20 Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/se= arch/sql/JCRSQLQueryBuilder.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/= apache/jackrabbit/core/search/sql/JCRSQLQueryBuilder.java?view=3Ddiff&r1=3D= 156922&r2=3D156923 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/s= ql/JCRSQLQueryBuilder.java (original) +++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/s= ql/JCRSQLQueryBuilder.java Thu Mar 10 01:57:09 2005 @@ -501,7 +501,7 @@ } else { int idx =3D names[i].indexOf('['); String name =3D null; - int index =3D 0; + int index =3D LocationStepQueryNode.NONE; if (idx > -1) { // contains index name =3D names[i].substring(0, idx); @@ -509,7 +509,7 @@ String indexStr =3D suffix.substring(1, suffix.length(= ) - 1); if (indexStr.equals("%")) { // select all same name siblings - index =3D 0; + index =3D LocationStepQueryNode.NONE; } else { try { index =3D Integer.parseInt(indexStr); @@ -517,14 +517,19 @@ log.warn("Unable to parse index for path eleme= nt: " + names[i]); } } + if (name.equals("%")) { + name =3D null; + } } else { - // no index + // no index specified + // - index defaults to 1 if there is an explicit name = test + // - index defaults to NONE if name test is % name =3D names[i]; - // in SQL this means index 1 - index =3D 1; - } - if (name.equals("%")) { - name =3D null; + if (name.equals("%")) { + name =3D null; + } else { + index =3D 1; + } } QName qName =3D null; if (name !=3D null) { Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/se= arch/sql/QueryFormat.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/= apache/jackrabbit/core/search/sql/QueryFormat.java?view=3Ddiff&r1=3D156922&= r2=3D156923 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/s= ql/QueryFormat.java (original) +++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/s= ql/QueryFormat.java Thu Mar 10 01:57:09 2005 @@ -338,7 +338,7 @@ } catch (NoPrefixDeclaredException e) { exceptions.add(e); } - if (node.getIndex() =3D=3D 0) { + if (node.getIndex() =3D=3D LocationStepQueryNode.NONE) { sb.append("[%]"); } else if (node.getIndex() =3D=3D 1) { // do nothing Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/se= arch/xpath/QueryFormat.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/= apache/jackrabbit/core/search/xpath/QueryFormat.java?view=3Ddiff&r1=3D15692= 2&r2=3D156923 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/x= path/QueryFormat.java (original) +++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/x= path/QueryFormat.java Thu Mar 10 01:57:09 2005 @@ -252,7 +252,7 @@ exceptions.add(e); } } - if (node.getIndex() > 0) { + if (node.getIndex() !=3D LocationStepQueryNode.NONE) { sb.append('[').append(node.getIndex()).append(']'); } QueryNode[] predicates =3D node.getPredicates(); @@ -268,7 +268,13 @@ StringBuffer sb =3D (StringBuffer) data; try { =20 - String propName =3D "@" + ISO9075.encode(node.getProperty()).t= oJCRName(resolver); + String propName =3D "@"; + // only encode if not position function + if (node.getProperty().equals(XPathQueryBuilder.FN_POSITION_FU= LL)) { + propName +=3D node.getProperty().toJCRName(resolver); + } else { + propName +=3D ISO9075.encode(node.getProperty()).toJCRName= (resolver); + } =20 if (node.getOperation() =3D=3D OPERATION_EQ_VALUE) { sb.append(propName).append(" eq "); @@ -358,6 +364,12 @@ cal.setTime(node.getDateValue()); b.append(XPathQueryBuilder.XS_DATETIME.toJCRName(resolver)); b.append("('").append(ISO8601.format(cal)).append("')"); + } else if (node.getValueType() =3D=3D TYPE_POSITION) { + if (node.getPositionValue() =3D=3D LocationStepQueryNode.LAST)= { + b.append("last()"); + } else { + b.append(node.getPositionValue()); + } } else { exceptions.add(new InvalidQueryException("Invalid type: " + no= de.getValueType())); } Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/se= arch/xpath/XPathQueryBuilder.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/= apache/jackrabbit/core/search/xpath/XPathQueryBuilder.java?view=3Ddiff&r1= =3D156922&r2=3D156923 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/x= path/XPathQueryBuilder.java (original) +++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/x= path/XPathQueryBuilder.java Thu Mar 10 01:57:09 2005 @@ -36,6 +36,7 @@ import org.apache.jackrabbit.core.search.QueryRootNode; import org.apache.jackrabbit.core.search.RelationQueryNode; import org.apache.jackrabbit.core.search.TextsearchQueryNode; +import org.apache.jackrabbit.core.search.QueryConstants; import org.apache.jackrabbit.core.util.ISO9075; =20 import javax.jcr.query.InvalidQueryException; @@ -61,6 +62,36 @@ static final QName FN_NOT_10 =3D new QName("", "not"); =20 /** + * QName for true function. + */ + static final QName FN_TRUE =3D new QName("", "true"); + + /** + * QName for false function. + */ + static final QName FN_FALSE =3D new QName("", "false"); + + /** + * QName for position function. + */ + static final QName FN_POSITION =3D new QName("", "position"); + + /** + * QName for the full position function including bracket + */ + static final QName FN_POSITION_FULL =3D new QName("", "position()"); + + /** + * QName for last function. + */ + static final QName FN_LAST =3D new QName("", "last"); + + /** + * QName for first function. + */ + static final QName FN_FIRST =3D new QName("", "first"); + + /** * QName for xs:dateTime */ static final QName XS_DATETIME =3D new QName(SearchManager.NS_XS_URI, = "dateTime"); @@ -71,6 +102,11 @@ static final QName JCRFN_LIKE =3D new QName(SearchManager.NS_JCRFN_URI= , "like"); =20 /** + * QName for jcrfn:deref + */ + static final QName JCRFN_DEREF =3D new QName(SearchManager.NS_JCRFN_UR= I, "deref"); + + /** * QName for jcrfn:contains */ static final QName JCRFN_CONTAINS =3D new QName(SearchManager.NS_JCRFN= _URI, "contains"); @@ -518,7 +554,13 @@ } else if (node.getId() =3D=3D JJTDOUBLELITERAL) { queryNode.setDoubleValue(Double.parseDouble(node.getValue())); } else if (node.getId() =3D=3D JJTINTEGERLITERAL) { - queryNode.setLongValue(Long.parseLong(node.getValue())); + // if this is an expression that contains position() do not ch= ange + // the type. + if (queryNode.getValueType() =3D=3D QueryConstants.TYPE_POSITI= ON) { + queryNode.setPositionValue(Integer.parseInt(node.getValue(= ))); + } else { + queryNode.setLongValue(Long.parseLong(node.getValue())); + } } else { exceptions.add(new InvalidQueryException("Unsupported literal = type:" + node.toString())); } @@ -634,6 +676,52 @@ // wrong number of arguments exceptions.add(new InvalidQueryException("Wrong number= of arguments for jcrfn:like")); } + } else if (FN_TRUE.toJCRName(resolver).equals(fName)) { + if (queryNode.getType() =3D=3D QueryNode.TYPE_RELATION) { + RelationQueryNode rel =3D (RelationQueryNode) queryNod= e; + rel.setStringValue("true"); + } else { + exceptions.add(new InvalidQueryException("Unsupported = location for true()")); + } + } else if (FN_FALSE.toJCRName(resolver).equals(fName)) { + if (queryNode.getType() =3D=3D QueryNode.TYPE_RELATION) { + RelationQueryNode rel =3D (RelationQueryNode) queryNod= e; + rel.setStringValue("false"); + } else { + exceptions.add(new InvalidQueryException("Unsupported = location for false()")); + } + } else if (FN_POSITION.toJCRName(resolver).equals(fName)) { + if (queryNode.getType() =3D=3D QueryNode.TYPE_RELATION) { + RelationQueryNode rel =3D (RelationQueryNode) queryNod= e; + if (rel.getOperation() =3D=3D RelationQueryNode.OPERAT= ION_EQ_GENERAL) { + // set dummy value to set type of relation query n= ode + // will be overwritten when the tree is furhter pa= rsed. + rel.setPositionValue(1); + rel.setProperty(FN_POSITION_FULL); + } else { + exceptions.add(new InvalidQueryException("Unsuppor= ted expression with position(). Only =3D is supported.")); + } + } else { + exceptions.add(new InvalidQueryException("Unsupported = location for position()")); + } + } else if (FN_FIRST.toJCRName(resolver).equals(fName)) { + if (queryNode.getType() =3D=3D QueryNode.TYPE_RELATION) { + ((RelationQueryNode) queryNode).setPositionValue(1); + } else if (queryNode.getType() =3D=3D QueryNode.TYPE_LOCAT= ION) { + ((LocationStepQueryNode) queryNode).setIndex(1); + } else { + exceptions.add(new InvalidQueryException("Unsupported = location for first()")); + } + } else if (FN_LAST.toJCRName(resolver).equals(fName)) { + if (queryNode.getType() =3D=3D QueryNode.TYPE_RELATION) { + ((RelationQueryNode) queryNode).setPositionValue(Locat= ionStepQueryNode.LAST); + } else if (queryNode.getType() =3D=3D QueryNode.TYPE_LOCAT= ION) { + ((LocationStepQueryNode) queryNode).setIndex(LocationS= tepQueryNode.LAST); + } else { + exceptions.add(new InvalidQueryException("Unsupported = location for last()")); + } + } else if (JCRFN_DEREF.toJCRName(resolver).equals(fName)) { + exceptions.add(new InvalidQueryException("Unsupported func= tion: " + fName)); } else { exceptions.add(new InvalidQueryException("Unsupported func= tion: " + fName)); } Modified: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/core/se= arch/SelectClauseTest.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/= apache/jackrabbit/core/search/SelectClauseTest.java?view=3Ddiff&r1=3D156922= &r2=3D156923 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/core/search/S= electClauseTest.java (original) +++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/core/search/S= electClauseTest.java Thu Mar 10 01:57:09 2005 @@ -102,7 +102,7 @@ testRootNode.save(); =20 String sql =3D "SELECT myvalue FROM " + ntBase + " WHERE " + - "jcr:path LIKE '" + testRoot + "/node' AND myvalue IS NOT = NULL"; + "jcr:path LIKE '" + testRoot + "/node[%]' AND myvalue IS N= OT NULL"; Query q =3D superuser.getWorkspace().getQueryManager().createQuery= (sql, Query.SQL); QueryResult result =3D q.execute(); checkResult(result, 2, 2); Modified: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/core/se= arch/XPathAxisTest.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/= apache/jackrabbit/core/search/XPathAxisTest.java?view=3Ddiff&r1=3D156922&r2= =3D156923 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/core/search/X= PathAxisTest.java (original) +++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/core/search/X= PathAxisTest.java Thu Mar 10 01:57:09 2005 @@ -167,4 +167,25 @@ String xpath =3D testPath + "/node1"; executeXPathQuery(xpath, new Node[]{n1}); } + + public void testIndex0Descendant() throws RepositoryException { + String xpath =3D "/jcr:root" + testRoot + "//*[0]"; + executeXPathQuery(xpath, new Node[0]); + } + + public void testIndex1Descendant() throws RepositoryException { + String xpath =3D "/jcr:root" + testRoot + "//*[1]"; + executeXPathQuery(xpath, new Node[]{n1, n11, n21}); + } + + public void testIndex2Descendant() throws RepositoryException { + String xpath =3D "/jcr:root" + testRoot + "//*[2]"; + executeXPathQuery(xpath, new Node[]{n2, n12, n22}); + } + + public void testIndex3Descendant() throws RepositoryException { + String xpath =3D "/jcr:root" + testRoot + "//*[3]"; + executeXPathQuery(xpath, new Node[0]); + } + } Modified: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/ap= i/query/XPathDocOrderTest.java URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/= apache/jackrabbit/test/api/query/XPathDocOrderTest.java?view=3Ddiff&r1=3D15= 6922&r2=3D156923 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/quer= y/XPathDocOrderTest.java (original) +++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/api/quer= y/XPathDocOrderTest.java Thu Mar 10 01:57:09 2005 @@ -64,6 +64,23 @@ } =20 /** + * Tests if position index and document order on child axis returns the + * correct node. + *

+ * For configuration description see {@link XPathDocOrderTest}. + */ + public void testDocOrderPositionIndex() throws Exception { + StringBuffer tmp =3D new StringBuffer("/"); + tmp.append(jcrRoot).append(testRoot).append("/*"); + tmp.append("[2]"); + String resultPath =3D ""; + for (NodeIterator nodes =3D testRootNode.getNodes(); nodes.hasNext= () && nodes.getPos() < 2;) { + resultPath =3D nodes.nextNode().getPath(); + } + docOrderTest(new Statement(tmp.toString(), Query.XPATH), resultPat= h); + } + + /** * Tests the last() function. *

* For configuration description see {@link XPathDocOrderTest}.