You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by mr...@apache.org on 2005/01/20 16:10:25 UTC

svn commit: r125778 - in incubator/jackrabbit/trunk/src: grammar/sql java/org/apache/jackrabbit/core java/org/apache/jackrabbit/core/search java/org/apache/jackrabbit/core/search/jcrql 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/test/search

Author: mreutegg
Date: Thu Jan 20 07:10:22 2005
New Revision: 125778

URL: http://svn.apache.org/viewcvs?view=rev&rev=125778
Log:
- Removed JCRQL implementation
- Added proper QName support to search
- redesigned parsing and formating of queries (better separation of abstract query tree and concrete syntax)
- Some improvements in SQL: colon is now supported in identifier without having to use double quotes, LIKE now supports escaping
Added:
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/QueryFormat.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/ISO9075.java   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/QueryFormat.java   (contents, props changed)
Removed:
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/jcrql/
Modified:
   incubator/jackrabbit/trunk/src/grammar/sql/JCRSQL.jjt
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AndQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/ExactQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/LocationStepQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NAryQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NodeTypeQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NotQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrderQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/PathQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryParser.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryRootNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RangeQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RelationQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/TextsearchQueryNode.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FilteredPropertyIterator.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LuceneQueryBuilder.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/MatchAllQuery.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PropertyIteratorImpl.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryImpl.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryResultImpl.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/WildcardTermEnum.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTIdentifier.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTPredicate.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/JCRSQLQueryBuilder.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/XPathQueryBuilder.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/FulltextQueryTest.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SelectClauseTest.java
   incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SimpleQueryTest.java

Modified: incubator/jackrabbit/trunk/src/grammar/sql/JCRSQL.jjt
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/grammar/sql/JCRSQL.jjt?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/grammar/sql/JCRSQL.jjt&r1=125777&p2=incubator/jackrabbit/trunk/src/grammar/sql/JCRSQL.jjt&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/grammar/sql/JCRSQL.jjt	(original)
+++ incubator/jackrabbit/trunk/src/grammar/sql/JCRSQL.jjt	Thu Jan 20 07:10:22 2005
@@ -41,23 +41,34 @@
  */
 package org.apache.jackrabbit.core.search.sql;
 
+import org.apache.jackrabbit.core.IllegalNameException;
+import org.apache.jackrabbit.core.NamespaceResolver;
+import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.UnknownPrefixException;
 import org.apache.jackrabbit.core.search.Constants;
 
 public class JCRSQLParser {
 
   private String statement;
 
+  private NamespaceResolver resolver;
+
   public static void main(String args[]) throws ParseException {
   	JCRSQLParser parser = new JCRSQLParser(System.in);
   	parser.Query().dump("");
   }
 
-  public static ASTQuery parse(String statement) throws ParseException {
+  public static ASTQuery parse(String statement, NamespaceResolver resolver) throws ParseException {
   	java.io.StringReader sReader = new java.io.StringReader(statement);
   	JCRSQLParser parser = new JCRSQLParser(sReader);
+  	parser.setNamespaceResolver(resolver);
   	return parser.Query();
   }
 
+  private void setNamespaceResolver(NamespaceResolver resolver) {
+        this.resolver = resolver;
+  }
+
 }
 
 PARSER_END(JCRSQLParser)
@@ -88,6 +99,7 @@
 | < FROM: "FROM" >
 | < ORDER: "ORDER" >
 | < WHERE: "WHERE" >
+| < ESCAPE: "ESCAPE" >
 | < SELECT: "SELECT" >
 | < BETWEEN: "BETWEEN" >
 | < CONTAINS: "CONTAINS" >
@@ -179,7 +191,7 @@
 
 
 | < REGULAR_IDENTIFIER: <IDENTIFIER_BODY> >
-| < #IDENTIFIER_BODY: <IDENTIFIER_START> (<UNDERSCORE> | <IDENTIFIER_PART>)* >
+| < #IDENTIFIER_BODY: <IDENTIFIER_START> (<UNDERSCORE> | <COLON> | <IDENTIFIER_PART>)* >
 | < #IDENTIFIER_START: <LETTER> > // syntax rules 5.2
 | < #IDENTIFIER_PART: <IDENTIFIER_START> | <DIGIT> >
 
@@ -282,9 +294,9 @@
 void Predicate() :
 {
   int operationType;
-  String identifier;
-  Token t;
+  QName identifier;
   String value;
+  String escapeString;
 }
 {
   identifier = Identifier() { jjtThis.setIdentifier(identifier); }
@@ -306,9 +318,9 @@
             ASTLiteral s = new ASTLiteral(JJTLITERAL);
             s.setType(Constants.TYPE_STRING);
             s.setValue(value);
-            s.jjtSetParent(jjtThis);
-            jjtThis.jjtAddChild(s, jjtThis.jjtGetNumChildren());
+            jjtree.pushNode(s);
           }
+          (<ESCAPE> escapeString = CharStringLiteral() { jjtThis.setEscapeString(escapeString); })?
         )
       )
     )
@@ -457,16 +469,34 @@
   }
 }
 
-String Identifier() :
+QName Identifier() :
 {
   Token t = null;
-  String name = null;
+  QName name = null;
 }
 {
   (
-    t = <REGULAR_IDENTIFIER> { jjtThis.setName(t.image); }
+    t = <REGULAR_IDENTIFIER>
+      {
+        try {
+          jjtThis.setName(QName.fromJCRName(t.image, resolver));
+        } catch (IllegalNameException e) {
+          throw new ParseException(e.getMessage());
+        } catch (UnknownPrefixException e) {
+          throw new ParseException(e.getMessage());
+        }
+      }
   |
-    t = <DELIMITED_IDENTIFIER> { jjtThis.setName(t.image.substring(1, t.image.length()-1)); }
+    t = <DELIMITED_IDENTIFIER>
+      {
+        try {
+          jjtThis.setName(QName.fromJCRName(t.image.substring(1, t.image.length()-1), resolver));
+        } catch (IllegalNameException e) {
+          throw new ParseException(e.getMessage());
+        } catch (UnknownPrefixException e) {
+          throw new ParseException(e.getMessage());
+        }
+      }
   |
     (
       (
@@ -485,7 +515,15 @@
         | t = <SELECT>
         | t = <BETWEEN>
       )
-      { jjtThis.setName(t.image); }
+      {
+        try {
+          jjtThis.setName(QName.fromJCRName(t.image, resolver));
+        } catch (IllegalNameException e) {
+          throw new ParseException(e.getMessage());
+        } catch (UnknownPrefixException e) {
+          throw new ParseException(e.getMessage());
+        }
+      }
     )
   )
   {

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SearchManager.java	Thu Jan 20 07:10:22 2005
@@ -40,6 +40,13 @@
 
 /**
  * Acts as a global entry point to execute queries and index nodes.
+ *
+ * @todo The SearchManager currently uses the system session to obtain an
+ * ItemStateManager from where it reads persistent ItemStates. This is kind
+ * of nasty, because the system session it is possible to change content through
+ * the system session as well.
+ * After switch to version 0.16 there is a shared ItemStateManager which
+ * represents the persistent view of item states.
  */
 public class SearchManager implements SynchronousEventListener {
 
@@ -55,6 +62,11 @@
     private static final String NS_XS_PREFIX = "xs";
     public static final String NS_XS_URI = "http://www.w3.org/2001/XMLSchema";
 
+    /** Namespace URI for JCR functions */
+    // @todo check if consistent with spec
+    private static final String NS_JCRFN_PREFIX = "jcrfn";
+    public static final String NS_JCRFN_URI = "http://www.jcp.org/jcr/xpath-functions/1.0";
+
     /** HierarchyManager for path resolution */
     private final HierarchyManager hmgr;
 
@@ -86,6 +98,12 @@
         } catch (RepositoryException e) {
             // not yet known
             nsReg.registerNamespace(NS_FN_PREFIX, NS_FN_URI);
+        }
+        try {
+            nsReg.getPrefix(NS_JCRFN_URI);
+        } catch (RepositoryException e) {
+            // not yet known
+            nsReg.registerNamespace(NS_JCRFN_PREFIX, NS_JCRFN_URI);
         }
 
         // initialize query handler

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AndQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AndQueryNode.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AndQueryNode.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AndQueryNode.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AndQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/AndQueryNode.java	Thu Jan 20 07:10:22 2005
@@ -55,74 +55,4 @@
         return visitor.visit(this, data);
     }
 
-    /**
-     * Returns a string representation of this query node including its sub-nodes.
-     * The returned string is formatted in JCRQL syntax.
-     *
-     * @return a string representation of this query node including its sub-nodes.
-     */
-    public String toJCRQLString() {
-        StringBuffer sb = new StringBuffer();
-        boolean bracket = false;
-        if (getParent() instanceof NotQueryNode) {
-            bracket = true;
-        }
-        if (bracket) {
-            sb.append("(");
-        }
-        String and = "";
-        for (Iterator it = operands.iterator(); it.hasNext();) {
-            sb.append(and);
-            sb.append(((QueryNode) it.next()).toJCRQLString());
-            and = " AND ";
-        }
-        if (bracket) {
-            sb.append(")");
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Returns a string representation of this query node including its sub-nodes.
-     * The returned string is formatted in JCR SQL syntax.
-     *
-     * @return a string representation of this query node including its sub-nodes.
-     */
-    public String toJCRSQLString() {
-        StringBuffer sb = new StringBuffer();
-        boolean bracket = false;
-        if (getParent() instanceof NotQueryNode) {
-            bracket = true;
-        }
-        if (bracket) {
-            sb.append("(");
-        }
-        String and = "";
-        for (Iterator it = operands.iterator(); it.hasNext();) {
-            sb.append(and);
-            sb.append(((QueryNode) it.next()).toJCRSQLString());
-            and = " AND ";
-        }
-        if (bracket) {
-            sb.append(")");
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Returns a string representation of this query node including its sub-nodes.
-     * The returned string is formatted in XPath syntax.
-     *
-     * @return a string representation of this query node including its sub-nodes.
-     */
-    public String toXPathString() {
-        StringBuffer sb = new StringBuffer();
-        String and = "";
-        for (Iterator it = operands.iterator(); it.hasNext();) {
-            sb.append(and);
-            sb.append(((QueryNode) it.next()).toXPathString());
-            and = " and ";
-        }
-        return sb.toString();
-    }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/ExactQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/ExactQueryNode.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/ExactQueryNode.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/ExactQueryNode.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/ExactQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/ExactQueryNode.java	Thu Jan 20 07:10:22 2005
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.core.search;
 
+import org.apache.jackrabbit.core.QName;
+
 /**
  * Implements a query node that defines an exact match of a property and a
  * value.
@@ -25,12 +27,12 @@
     /**
      * The name of the property to match
      */
-    private final String property;
+    private final QName property;
 
     /**
      * The value of the property to match
      */
-    private final String value;
+    private final QName value;
 
     /**
      * Creates a new <code>ExactQueryNode</code> instance.
@@ -39,7 +41,7 @@
      * @param property the name of the property to match.
      * @param value    the value of the property to match.
      */
-    public ExactQueryNode(QueryNode parent, String property, String value) {
+    public ExactQueryNode(QueryNode parent, QName property, QName value) {
         super(parent);
         if (parent == null) {
             throw new NullPointerException("parent");
@@ -60,7 +62,7 @@
      *
      * @return the name of the property to match.
      */
-    public String getPropertyName() {
+    public QName getPropertyName() {
         return property;
     }
 
@@ -69,38 +71,8 @@
      *
      * @return the value of the property to match.
      */
-    public String getValue() {
+    public QName getValue() {
         return value;
     }
 
-    /**
-     * Returns a JCRQL representation for this query node.
-     *
-     * @return a JCRQL representation for this query node.
-     */
-    public String toJCRQLString() {
-        if (property.indexOf(' ') > -1) {
-            return "\"" + property + "\"=\"" + value + "\"";
-        }
-        return property + "=\"" + value + "\"";
-    }
-
-    /**
-     * Returns a JCR SQL representation for this query node.
-     *
-     * @return a JCR SQL representation for this query node.
-     */
-    public String toJCRSQLString() {
-        return "\"" + property + "\"='" + value + "'";
-    }
-
-    /**
-     * Returns an XPath representation for this query node.
-     *
-     * @return an XPath representation for this query node.
-     */
-    public String toXPathString() {
-        // todo use encoding for property name
-        return "@" + property + "='" + value.replaceAll("'", "''") + "'";
-    }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/LocationStepQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/LocationStepQueryNode.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/LocationStepQueryNode.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/LocationStepQueryNode.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/LocationStepQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/LocationStepQueryNode.java	Thu Jan 20 07:10:22 2005
@@ -16,7 +16,7 @@
  */
 package org.apache.jackrabbit.core.search;
 
-import java.util.Iterator;
+import org.apache.jackrabbit.core.QName;
 
 /**
  * Defines a location step for querying the path of a node.
@@ -37,7 +37,7 @@
      * Name test for this location step. A <code>null</code> value indicates
      * a '*' name test.
      */
-    private String nameTest;
+    private QName nameTest;
 
     /**
      * If set to <code>true</code> this location step uses the descendant-or-self
@@ -49,7 +49,7 @@
      * If <code>index</code> is larger than 0 this location step contains
      * a position index.
      */
-    private int index = -1;
+    private int index = 0;
 
     /**
      * Creates a new <code>LocationStepQueryNode</code> with a reference to
@@ -60,7 +60,7 @@
      * @param descendants if <code>true</code> this location step uses the
      *   descendant-or-self axis; otherwise the child axis.
      */
-    public LocationStepQueryNode(QueryNode parent, String nameTest, boolean descendants) {
+    public LocationStepQueryNode(QueryNode parent, QName nameTest, boolean descendants) {
         super(parent);
         this.nameTest = nameTest;
         this.includeDescendants = descendants;
@@ -71,7 +71,7 @@
      * if the name test is '*'.
      * @return the label of the node for this location step.
      */
-    public String getNameTest() {
+    public QName getNameTest() {
         return nameTest;
     }
 
@@ -79,7 +79,7 @@
      * Sets a new name test.
      * @param nameTest the name test or <code>null</code> to match all names.
      */
-    public void setNameTest(String nameTest) {
+    public void setNameTest(QName nameTest) {
         this.nameTest = nameTest;
     }
 
@@ -126,15 +126,23 @@
     }
 
     /**
-     * Sets the position index for this step.
+     * Sets the position index for this step. A value of 0 (zero) indicates
+     * 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 = index;
     }
 
     /**
-     * Returns the position index for this step.
+     * Returns the position index for this step. A value of 0 (zero) 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.
      */
     public int getIndex() {
@@ -148,66 +156,4 @@
         return visitor.visit(this, data);
     }
 
-    /**
-     * Returns a JCRQL representation for this query node.
-     *
-     * @return a JCRQL representation for this query node.
-     */
-    public String toJCRQLString() {
-        StringBuffer sb = new StringBuffer();
-        if (nameTest == null) {
-            sb.append("*");
-        } else {
-            sb.append(nameTest);
-        }
-        if (index > -1) {
-            sb.append('[').append(index).append(']');
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Returns a JCR SQL representation for this query node.
-     *
-     * @return a JCR SQL representation for this query node.
-     */
-    public String toJCRSQLString() {
-        StringBuffer sb = new StringBuffer();
-        if (nameTest == null) {
-            sb.append("*");
-        } else {
-            sb.append(nameTest);
-        }
-        if (index > -1) {
-            sb.append('[').append(index).append(']');
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Returns an XPath representation for this query node.
-     *
-     * @return an XPath representation for this query node.
-     */
-    public String toXPathString() {
-        StringBuffer sb = new StringBuffer();
-        if (includeDescendants) {
-            sb.append('/');
-        }
-        if (nameTest == null) {
-            sb.append("*");
-        } else {
-            sb.append(nameTest);
-        }
-        if (index > -1) {
-            sb.append('[').append(index).append(']');
-        }
-        if (operands != null) {
-            for (Iterator it = operands.iterator(); it.hasNext();) {
-                QueryNode predicate = (QueryNode) it.next();
-                sb.append('[').append(predicate.toXPathString()).append(']');
-            }
-        }
-        return sb.toString();
-    }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NAryQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NAryQueryNode.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NAryQueryNode.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NAryQueryNode.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NAryQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NAryQueryNode.java	Thu Jan 20 07:10:22 2005
@@ -54,7 +54,10 @@
      */
     public NAryQueryNode(QueryNode parent, QueryNode[] operands) {
         super(parent);
-        this.operands.addAll(Arrays.asList(operands));
+        if (operands.length > 0) {
+            this.operands = new ArrayList();
+            this.operands.addAll(Arrays.asList(operands));
+        }
     }
 
     /**
@@ -67,6 +70,20 @@
             operands = new ArrayList();
         }
         operands.add(operand);
+    }
+
+    /**
+     * Returns an array of currently set <code>QueryNode</code> operands of this
+     * <code>QueryNode</code>. Returns an empty array if no operands are set.
+     *
+     * @return currently set <code>QueryNode</code> operands.
+     */
+    public QueryNode[] getOperands() {
+        if (operands == null) {
+            return new QueryNode[0];
+        } else {
+            return (QueryNode[]) operands.toArray(new QueryNode[operands.size()]);
+        }
     }
 
     /**

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NodeTypeQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NodeTypeQueryNode.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NodeTypeQueryNode.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NodeTypeQueryNode.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NodeTypeQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NodeTypeQueryNode.java	Thu Jan 20 07:10:22 2005
@@ -17,6 +17,7 @@
 package org.apache.jackrabbit.core.search;
 
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
+import org.apache.jackrabbit.core.QName;
 
 /**
  * Implements a query node that defines a node type match.
@@ -29,11 +30,11 @@
      * @param parent   the parent node for this query node.
      * @param nodeType the name of the node type.
      */
-    public NodeTypeQueryNode(QueryNode parent, String nodeType) {
+    public NodeTypeQueryNode(QueryNode parent, QName nodeType) {
         // we only use the jcr primary type as a dummy value
         // the property name is actually replaced in the query builder
         // when the runtime query is created to search the index.
-        super(parent, NodeTypeRegistry.JCR_PRIMARY_TYPE.toString(), nodeType);
+        super(parent, NodeTypeRegistry.JCR_PRIMARY_TYPE, nodeType);
     }
 
     /**

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NotQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NotQueryNode.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NotQueryNode.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NotQueryNode.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NotQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/NotQueryNode.java	Thu Jan 20 07:10:22 2005
@@ -49,39 +49,4 @@
         return visitor.visit(this, data);
     }
 
-    /**
-     * Returns a JCRQL representation for this query node.
-     *
-     * @return a JCRQL representation for this query node.
-     */
-    public String toJCRQLString() {
-        if (operands.size() > 0) {
-            return "NOT " + ((QueryNode) operands.get(0)).toJCRQLString();
-        }
-        return "";
-    }
-
-    /**
-     * Returns a JCR SQL representation for this query node.
-     *
-     * @return a JCR SQL representation for this query node.
-     */
-    public String toJCRSQLString() {
-        if (operands.size() > 0) {
-            return "NOT " + ((QueryNode) operands.get(0)).toJCRSQLString();
-        }
-        return "";
-    }
-
-    /**
-     * Returns an XPath representation for this query node.
-     *
-     * @return an XPath representation for this query node.
-     */
-    public String toXPathString() {
-        if (operands.size() > 0) {
-            return "fn:not(" + ((QueryNode) operands.get(0)).toXPathString() + ")";
-        }
-        return "";
-    }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrQueryNode.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrQueryNode.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrQueryNode.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrQueryNode.java	Thu Jan 20 07:10:22 2005
@@ -16,8 +16,6 @@
  */
 package org.apache.jackrabbit.core.search;
 
-import java.util.Iterator;
-
 /**
  * Implements a query node that defines an OR operation between arbitrary
  * other {@link QueryNode}s.
@@ -53,88 +51,4 @@
         return visitor.visit(this, data);
     }
 
-    /**
-     * Returns a string representation of this query node including its sub-nodes.
-     * The returned string is formatted in JCRQL syntax.
-     *
-     * @return a string representation of this query node including its sub-nodes.
-     */
-    public String toJCRQLString() {
-        StringBuffer sb = new StringBuffer();
-        boolean bracket = false;
-        if (getParent() instanceof LocationStepQueryNode
-                || getParent() instanceof AndQueryNode
-                || getParent() instanceof NotQueryNode) {
-            bracket = true;
-        }
-        if (bracket) {
-            sb.append("(");
-        }
-        String or = "";
-        for (Iterator it = operands.iterator(); it.hasNext();) {
-            sb.append(or);
-            sb.append(((QueryNode) it.next()).toJCRQLString());
-            or = " OR ";
-        }
-        if (bracket) {
-            sb.append(")");
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Returns a string representation of this query node including its sub-nodes.
-     * The returned string is formatted in JCR SQL syntax.
-     *
-     * @return a string representation of this query node including its sub-nodes.
-     */
-    public String toJCRSQLString() {
-        StringBuffer sb = new StringBuffer();
-        boolean bracket = false;
-        if (getParent() instanceof LocationStepQueryNode 
-                || getParent() instanceof AndQueryNode
-                || getParent() instanceof NotQueryNode) {
-            bracket = true;
-        }
-        if (bracket) {
-            sb.append("(");
-        }
-        String or = "";
-        for (Iterator it = operands.iterator(); it.hasNext();) {
-            sb.append(or);
-            sb.append(((QueryNode) it.next()).toJCRSQLString());
-            or = " OR ";
-        }
-        if (bracket) {
-            sb.append(")");
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Returns a string representation of this query node including its sub-nodes.
-     * The returned string is formatted in XPath syntax.
-     *
-     * @return a string representation of this query node including its sub-nodes.
-     */
-    public String toXPathString() {
-        StringBuffer sb = new StringBuffer();
-        boolean bracket = false;
-        if (getParent() instanceof AndQueryNode) {
-            bracket = true;
-        }
-        if (bracket) {
-            sb.append("(");
-        }
-        String or = "";
-        for (Iterator it = operands.iterator(); it.hasNext();) {
-            sb.append(or);
-            sb.append(((QueryNode) it.next()).toXPathString());
-            or = " or ";
-        }
-        if (bracket) {
-            sb.append(")");
-        }
-        return sb.toString();
-    }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrderQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrderQueryNode.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrderQueryNode.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrderQueryNode.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrderQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/OrderQueryNode.java	Thu Jan 20 07:10:22 2005
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.core.search;
 
+import org.apache.jackrabbit.core.QName;
+
 /**
  * Implements a query node that defines the order of nodes according to the
  * values of properties.
@@ -25,7 +27,7 @@
     /**
      * The name of the properties to order
      */
-    private String[] properties;
+    private QName[] properties;
 
     /**
      * Array of flag indicating whether a node is ordered ascending or descending
@@ -41,9 +43,11 @@
      * @param orderSpecs if <code>true</code> a result node is orderd ascending;
      *                   otherwise descending.
      */
-    public OrderQueryNode(QueryNode parent, String[] properties, boolean[] orderSpecs) {
+    public OrderQueryNode(QueryNode parent, QName[] properties, boolean[] orderSpecs) {
         super(parent);
-        if (properties.length != orderSpecs.length)
+        if (properties.length != orderSpecs.length) {
+            throw new IllegalArgumentException("Number of propertes and orderSpecs must be the same");
+        }
         this.properties = properties;
         this.orderSpecs = orderSpecs;
     }
@@ -71,12 +75,12 @@
     }
 
     /**
-     * Returns a String array that contains the name of the properties
+     * Returns a <code>QName</code> array that contains the name of the properties
      * to sort the result nodes.
      *
      * @return names of order properties.
      */
-    public String[] getOrderByProperties() {
+    public QName[] getOrderByProperties() {
         return properties;
     }
 
@@ -89,59 +93,4 @@
         return orderSpecs;
     }
 
-    /**
-     * Returns a JCRQL representation for this query node.
-     *
-     * @return a JCRQL representation for this query node.
-     */
-    public String toJCRQLString() {
-        StringBuffer sb = new StringBuffer("ORDER BY");
-        if (properties.length > 0) {
-            String comma = "";
-            for (int i = 0; i < properties.length; i++) {
-                sb.append(comma).append(" ");
-                sb.append(properties[i]);
-                if (isAscending(i)) {
-                    // FIXME really default to descending?
-                    sb.append(" ASCENDING");
-                }
-                comma = ",";
-            }
-        } else {
-            sb.append(" SCORE");
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Returns a JCR SQL representation for this query node.
-     *
-     * @return a JCR SQL representation for this query node.
-     */
-    public String toJCRSQLString() {
-        StringBuffer sb = new StringBuffer("ORDER BY");
-        if (properties.length > 0) {
-            String comma = "";
-            for (int i = 0; i < properties.length; i++) {
-                sb.append(comma).append(" \"");
-                sb.append(properties[i]).append("\"");
-                if (!isAscending(i)) {
-                    sb.append(" DESC");
-                }
-                comma = ",";
-            }
-        } else {
-            sb.append(" SCORE");
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Returns an XPath representation for this query node.
-     *
-     * @return an XPath representation for this query node.
-     */
-    public String toXPathString() {
-        return "";
-    }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/PathQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/PathQueryNode.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/PathQueryNode.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/PathQueryNode.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/PathQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/PathQueryNode.java	Thu Jan 20 07:10:22 2005
@@ -57,61 +57,4 @@
         }
     }
 
-    /**
-     * Returns a JCRQL representation for this query node.
-     *
-     * @return a JCRQL representation for this query node.
-     */
-    public String toJCRQLString() {
-        StringBuffer sb = new StringBuffer("LOCATION \"");
-        LocationStepQueryNode[] steps = getPathSteps();
-        for (int i = 0; i < steps.length; i++) {
-            if (steps[i].getNameTest() == null
-                    || steps[i].getNameTest().length() > 0) {
-                sb.append('/');
-            }
-            sb.append(steps[i].toJCRQLString());
-        }
-        sb.append('"');
-        return sb.toString();
-    }
-
-
-    /**
-     * Returns a JCR SQL representation for this query node.
-     *
-     * @return a JCR SQL representation for this query node.
-     */
-    public String toJCRSQLString() {
-        // FIXME implement namespace awareness
-        StringBuffer sb = new StringBuffer("\"jcr:path\"='");
-        LocationStepQueryNode[] steps = getPathSteps();
-        for (int i = 0; i < steps.length; i++) {
-            if (steps[i].getNameTest() == null
-                    || steps[i].getNameTest().length() > 0) {
-                sb.append('/');
-            }
-            sb.append(steps[i].toJCRSQLString());
-        }
-        sb.append('\'');
-        return sb.toString();
-    }
-
-    /**
-     * Returns an XPath representation for this query node.
-     *
-     * @return an XPath representation for this query node.
-     */
-    public String toXPathString() {
-        StringBuffer sb = new StringBuffer();
-        LocationStepQueryNode[] steps = getPathSteps();
-        for (int i = 0; i < steps.length; i++) {
-            if (steps[i].getNameTest() == null
-                    || steps[i].getNameTest().length() > 0) {
-                sb.append('/');
-            }
-            sb.append(steps[i].toXPathString());
-        }
-        return sb.toString();
-    }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNode.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNode.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNode.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryNode.java	Thu Jan 20 07:10:22 2005
@@ -61,27 +61,4 @@
      */
     public abstract Object accept(QueryNodeVisitor visitor, Object data);
 
-    /**
-     * Returns a string representation of this query node including its sub-nodes.
-     * The returned string is formatted in JCRQL syntax.
-     *
-     * @return a string representation of this query node including its sub-nodes.
-     */
-    public abstract String toJCRQLString();
-
-    /**
-     * Returns a string representation of this query node including its sub-nodes.
-     * The returned string is formatted in JCRQL syntax.
-     *
-     * @return a string representation of this query node including its sub-nodes.
-     */
-    public abstract String toJCRSQLString();
-
-    /**
-     * Returns a string representation of this query node including its sub-nodes.
-     * The returned string is formatted in XPath syntax.
-     *
-     * @return a string representation of this query node including its sub-nodes.
-     */
-    public abstract String toXPathString();
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryParser.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryParser.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryParser.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryParser.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryParser.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryParser.java	Thu Jan 20 07:10:22 2005
@@ -16,7 +16,6 @@
  */
 package org.apache.jackrabbit.core.search;
 
-import org.apache.jackrabbit.core.search.jcrql.JCRQLQueryBuilder;
 import org.apache.jackrabbit.core.search.xpath.XPathQueryBuilder;
 import org.apache.jackrabbit.core.search.sql.JCRSQLQueryBuilder;
 import org.apache.jackrabbit.core.NamespaceResolver;
@@ -55,14 +54,45 @@
                                       NamespaceResolver resolver)
             throws InvalidQueryException {
 
-        if (Query.JCRQL.equals(language)) {
-            return JCRQLQueryBuilder.createQuery(statement);
-        } else if (Query.XPATH_DOCUMENT_VIEW.equals(language)) {
+        if (Query.XPATH_DOCUMENT_VIEW.equals(language)) {
             return XPathQueryBuilder.createQuery(statement, resolver);
         } else if ("sql".equals(language)) {
             return JCRSQLQueryBuilder.createQuery(statement, resolver);
         } else {
-            throw new InvalidQueryException("unknown language");
+            throw new InvalidQueryException("Unsupported language: " + language);
+        }
+    }
+
+    /**
+     * Creates a String representation of the QueryNode tree argument
+     * <code>root</code>. The argument <code>language</code> specifies the
+     * syntax.
+     * See also: {@link javax.jcr.query.QueryManager#getSupportedQueryLanguages()}.
+     *
+     * @param root the query node tree.
+     * @param language one of the languages returned by:
+     *   {@link javax.jcr.query.QueryManager#getSupportedQueryLanguages()}.
+     * @param resolver to resolve QNames.
+     *
+     * @return a String representation of the query node tree.
+     *
+     * @throws InvalidQueryException if the query node tree cannot be converted
+     * into a String representation of the given language. This might be due to
+     * syntax restrictions of the given language. This exception is also thrown
+     * if <code>language</code> is not one of the supported query languages
+     * returned by the {@link javax.jcr.query.QueryManager}.
+     */
+    public static String toString(QueryRootNode root,
+                                  String language,
+                                  NamespaceResolver resolver)
+            throws InvalidQueryException {
+
+        if (Query.XPATH_DOCUMENT_VIEW.equals(language)) {
+            return XPathQueryBuilder.toString(root, resolver);
+        } else if ("sql".equals(language)) {
+            return JCRSQLQueryBuilder.toString(root, resolver);
+        } else {
+            throw new InvalidQueryException("Unsupported language: " + language);
         }
     }
 

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryRootNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryRootNode.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryRootNode.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryRootNode.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryRootNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/QueryRootNode.java	Thu Jan 20 07:10:22 2005
@@ -16,8 +16,9 @@
  */
 package org.apache.jackrabbit.core.search;
 
+import org.apache.jackrabbit.core.QName;
+
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -31,13 +32,8 @@
     private PathQueryNode locationNode;
 
     /**
-     * The list of nodeType constraints. Might be null
-     * @todo not used anymore, node types can be specified in any predicate.
-     */
-    private List nodeTypes = new ArrayList();
-
-    /**
-     * The list of property names to select. Might be null
+     * The list of property names (as {@link org.apache.jackrabbit.core.QName}s
+     * to select.
      */
     private List selectProperties = new ArrayList();
 
@@ -78,7 +74,7 @@
      *
      * @param propName the name of the property to select.
      */
-    public void addSelectProperty(String propName) {
+    public void addSelectProperty(QName propName) {
         selectProperties.add(propName);
     }
 
@@ -87,8 +83,8 @@
      *
      * @return an array of select properties.
      */
-    public String[] getSelectProperties() {
-        return (String[]) selectProperties.toArray(new String[selectProperties.size()]);
+    public QName[] getSelectProperties() {
+        return (QName[]) selectProperties.toArray(new QName[selectProperties.size()]);
     }
 
     /**
@@ -108,7 +104,6 @@
     public void setOrderNode(OrderQueryNode orderNode) {
         this.orderNode = orderNode;
     }
-    //--------------------------------------------------------------------------
 
     /**
      * @see QueryNode#accept(org.apache.jackrabbit.core.search.QueryNodeVisitor, java.lang.Object)
@@ -117,89 +112,4 @@
         return visitor.visit(this, data);
     }
 
-
-    /**
-     * Returns a string representation of this query node including its sub-nodes.
-     * The returned string is formatted in JCRQL syntax.
-     *
-     * @return a string representation of this query node including its sub-nodes.
-     */
-    public String toJCRQLString() {
-        StringBuffer sb = new StringBuffer("SELECT *");
-        String comma = "";
-        if (nodeTypes.size() > 0) {
-            sb.append(" FROM");
-        }
-        for (Iterator it = nodeTypes.iterator(); it.hasNext();) {
-            NodeTypeQueryNode nodeType = (NodeTypeQueryNode) it.next();
-            sb.append(comma);
-            sb.append(" ").append(nodeType.getValue());
-            comma = ",";
-        }
-        if (locationNode != null) {
-            sb.append(" ").append(locationNode.toJCRQLString());
-        }
-        LocationStepQueryNode[] steps = locationNode.getPathSteps();
-        QueryNode[] predicates = steps[steps.length - 1].getPredicates();
-        String and = "";
-        for (int i = 0; i < predicates.length; i++) {
-            if (i == 0) {
-                sb.append(" WHERE ");
-            }
-            sb.append(and).append(predicates[i].toJCRQLString());
-            and = " AND ";
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Returns a string representation of this query node including its sub-nodes.
-     * The returned string is formatted in JCR SQL syntax.
-     *
-     * @return a string representation of this query node including its sub-nodes.
-     */
-    public String toJCRSQLString() {
-        StringBuffer sb = new StringBuffer("SELECT *");
-        sb.append(" FROM");
-        String comma = "";
-        if (nodeTypes.size() > 0) {
-            for (Iterator it = nodeTypes.iterator(); it.hasNext();) {
-                NodeTypeQueryNode nodeType = (NodeTypeQueryNode) it.next();
-                sb.append(comma);
-                sb.append(" \"").append(nodeType.getValue()).append("\"");
-                comma = ",";
-            }
-        } else {
-            sb.append(" nt:base");
-        }
-        LocationStepQueryNode[] steps = locationNode.getPathSteps();
-        QueryNode[] predicates = steps[steps.length - 1].getPredicates();
-        String and = "";
-        for (int i = 0; i < predicates.length; i++) {
-            if (i == 0) {
-                sb.append(" WHERE ");
-            }
-            sb.append(and).append(predicates[i].toJCRSQLString());
-            and = " AND ";
-        }
-
-        if (steps.length == 2
-                && steps[1].getIncludeDescendants()
-                && steps[1].getNameTest() == null) {
-            // then this query selects all paths
-        } else {
-            sb.append(" AND ").append(locationNode.toJCRSQLString());
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Returns a string representation of this query node including its sub-nodes.
-     * The returned string is formatted in XPath syntax.
-     *
-     * @return a string representation of this query node including its sub-nodes.
-     */
-    public String toXPathString() {
-        return locationNode.toXPathString();
-    }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RangeQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RangeQueryNode.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RangeQueryNode.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RangeQueryNode.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RangeQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RangeQueryNode.java	Thu Jan 20 07:10:22 2005
@@ -27,6 +27,7 @@
  * <li><code>String</code></li>
  * <li><code>Date</code></li>
  * </ul>
+ * @todo remove this class. not used anymore
  */
 public class RangeQueryNode extends QueryNode implements Constants {
 
@@ -167,30 +168,4 @@
         return type;
     }
 
-    /**
-     * Returns a JCRQL representation for this query node.
-     *
-     * @return a JCRQL representation for this query node.
-     */
-    public String toJCRQLString() {
-        return "";
-    }
-
-    /**
-     * Returns a JCR SQL representation for this query node.
-     *
-     * @return a JCR SQL representation for this query node.
-     */
-    public String toJCRSQLString() {
-        return "";
-    }
-
-    /**
-     * Returns an XPath representation for this query node.
-     *
-     * @return an XPath representation for this query node.
-     */
-    public String toXPathString() {
-        return "";
-    }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RelationQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RelationQueryNode.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RelationQueryNode.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RelationQueryNode.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RelationQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/RelationQueryNode.java	Thu Jan 20 07:10:22 2005
@@ -16,10 +16,9 @@
  */
 package org.apache.jackrabbit.core.search;
 
-import javax.jcr.util.ISO8601;
-import java.util.Calendar;
+import org.apache.jackrabbit.core.QName;
+
 import java.util.Date;
-import java.util.TimeZone;
 
 /**
  * Implements a query node that defines property value relation.
@@ -29,7 +28,7 @@
     /**
      * The name of the property
      */
-    private String property;
+    private QName property;
 
     /**
      * The <code>long</code> value of the relation if this is a query is of type
@@ -87,7 +86,7 @@
      * @param value     a property value
      * @param operation the type of the relation.
      */
-    public RelationQueryNode(QueryNode parent, String property, long value, int operation) {
+    public RelationQueryNode(QueryNode parent, QName property, long value, int operation) {
         super(parent);
         this.property = property;
         this.valueLong = value;
@@ -104,7 +103,7 @@
      * @param value     a property value
      * @param operation the type of the relation.
      */
-    public RelationQueryNode(QueryNode parent, String property, double value, int operation) {
+    public RelationQueryNode(QueryNode parent, QName property, double value, int operation) {
         super(parent);
         this.property = property;
         this.valueDouble = value;
@@ -121,7 +120,7 @@
      * @param value     a property value
      * @param operation the type of the relation.
      */
-    public RelationQueryNode(QueryNode parent, String property, Date value, int operation) {
+    public RelationQueryNode(QueryNode parent, QName property, Date value, int operation) {
         super(parent);
         this.property = property;
         this.valueDate = value;
@@ -138,7 +137,7 @@
      * @param value     a property value
      * @param operation the type of the relation.
      */
-    public RelationQueryNode(QueryNode parent, String property, String value, int operation) {
+    public RelationQueryNode(QueryNode parent, QName property, String value, int operation) {
         super(parent);
         this.property = property;
         this.valueString = value;
@@ -167,7 +166,7 @@
      *
      * @return the name of the property in this relation query node.
      */
-    public String getProperty() {
+    public QName getProperty() {
         return property;
     }
 
@@ -175,7 +174,7 @@
      * Sets a new property name for this relation query node.
      * @param name the new property name.
      */
-    public void setProperty(String name) {
+    public void setProperty(QName name) {
         property = name;
     }
 
@@ -264,142 +263,4 @@
         return operation;
     }
 
-    /**
-     * Returns a JCRQL representation for this query node.
-     *
-     * @return a JCRQL representation for this query node.
-     */
-    public String toJCRQLString() {
-        StringBuffer sb = new StringBuffer();
-        if (property.indexOf(' ') > -1) {
-            sb.append("\"" + property + "\"");
-        } else {
-            sb.append(property);
-        }
-
-        if (operation == OPERATION_EQ) {
-            sb.append(" = ");
-        } else if (operation == OPERATION_GE) {
-            sb.append(" >= ");
-        } else if (operation == OPERATION_GT) {
-            sb.append(" > ");
-        } else if (operation == OPERATION_LE) {
-            sb.append(" <= ");
-        } else if (operation == OPERATION_LIKE) {
-            sb.append(" LIKE ");
-        } else if (operation == OPERATION_LT) {
-            sb.append(" < ");
-        } else if (operation == OPERATION_NE) {
-            sb.append(" <> ");
-        } else {
-            throw new RuntimeException("invalid operation: " + operation);
-        }
-
-
-        if (type == TYPE_LONG) {
-            sb.append(valueLong);
-        } else if (type == TYPE_DOUBLE) {
-            sb.append(valueDouble);
-        } else if (type == TYPE_STRING) {
-            sb.append("\"").append(valueString).append("\"");
-        } else if (type == TYPE_DATE || type == TYPE_TIMESTAMP) {
-            Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
-            cal.setTime(valueDate);
-            sb.append(ISO8601.format(cal));
-        } else {
-            throw new RuntimeException("Invalid type: " + type);
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Returns a JCR SQL representation for this query node.
-     *
-     * @return a JCR SQL representation for this query node.
-     */
-    public String toJCRSQLString() {
-        StringBuffer sb = new StringBuffer();
-        sb.append("\"" + property + "\"");
-
-        if (operation == OPERATION_EQ) {
-            sb.append(" = ");
-        } else if (operation == OPERATION_GE) {
-            sb.append(" >= ");
-        } else if (operation == OPERATION_GT) {
-            sb.append(" > ");
-        } else if (operation == OPERATION_LE) {
-            sb.append(" <= ");
-        } else if (operation == OPERATION_LIKE) {
-            sb.append(" LIKE ");
-        } else if (operation == OPERATION_LT) {
-            sb.append(" < ");
-        } else if (operation == OPERATION_NE) {
-            sb.append(" <> ");
-        } else {
-            throw new RuntimeException("invalid operation: " + operation);
-        }
-
-
-        if (type == TYPE_LONG) {
-            sb.append(valueLong);
-        } else if (type == TYPE_DOUBLE) {
-            sb.append(valueDouble);
-        } else if (type == TYPE_STRING) {
-            sb.append("'").append(valueString.replaceAll("'", "''")).append("'");
-        } else if (type == TYPE_DATE || type == TYPE_TIMESTAMP) {
-            Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
-            cal.setTime(valueDate);
-            sb.append("TIMESTAMP '").append(ISO8601.format(cal)).append("'");
-        } else {
-            throw new RuntimeException("Invalid type: " + type);
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Returns an XPath representation for this query node.
-     *
-     * @return an XPath representation for this query node.
-     */
-    public String toXPathString() {
-        StringBuffer sb = new StringBuffer();
-        // @todo use escaping for property name
-        sb.append("@" + property);
-
-        if (operation == OPERATION_EQ) {
-            sb.append(" = ");
-        } else if (operation == OPERATION_GE) {
-            sb.append(" >= ");
-        } else if (operation == OPERATION_GT) {
-            sb.append(" > ");
-        } else if (operation == OPERATION_LE) {
-            sb.append(" <= ");
-        } else if (operation == OPERATION_LIKE) {
-            // @todo make namespace aware
-            sb.insert(0, "jcrfn:like(").append(",");
-        } else if (operation == OPERATION_LT) {
-            sb.append(" < ");
-        } else if (operation == OPERATION_NE) {
-            sb.append(" != ");
-        } else {
-            throw new RuntimeException("invalid operation: " + operation);
-        }
-
-
-        if (type == TYPE_LONG) {
-            sb.append(valueLong);
-        } else if (type == TYPE_DOUBLE) {
-            sb.append(valueDouble);
-        } else if (type == TYPE_STRING) {
-            sb.append("'").append(valueString.replaceAll("'", "''")).append("'");
-        } else if (type == TYPE_DATE || type == TYPE_TIMESTAMP) {
-            Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
-            cal.setTime(valueDate);
-            // @todo make namespace aware
-            sb.append("xs:dateTime('").append(ISO8601.format(cal)).append("')");
-        } else {
-            throw new RuntimeException("Invalid type: " + type);
-        }
-        return sb.toString();
-    }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/TextsearchQueryNode.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/TextsearchQueryNode.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/TextsearchQueryNode.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/TextsearchQueryNode.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/TextsearchQueryNode.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/TextsearchQueryNode.java	Thu Jan 20 07:10:22 2005
@@ -54,25 +54,4 @@
         return query;
     }
 
-    /**
-     * Returns a JCRQL representation for this query node.
-     *
-     * @return a JCRQL representation for this query node.
-     */
-    public String toJCRQLString() {
-        return "TEXTSEARCH \"" + query + "\"";
-    }
-
-    public String toJCRSQLString() {
-        return "CONTAINS('" + query + "')";
-    }
-
-    /**
-     * Returns an XPath representation for this query node.
-     *
-     * @return an XPath representation for this query node.
-     */
-    public String toXPathString() {
-        return "jcrfn:contains('" + query.replaceAll("'", "''") + "')";
-    }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FilteredPropertyIterator.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FilteredPropertyIterator.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FilteredPropertyIterator.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FilteredPropertyIterator.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FilteredPropertyIterator.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FilteredPropertyIterator.java	Thu Jan 20 07:10:22 2005
@@ -17,6 +17,9 @@
 package org.apache.jackrabbit.core.search.lucene;
 
 import org.apache.log4j.Logger;
+import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.NamespaceResolver;
+import org.apache.jackrabbit.core.NoPrefixDeclaredException;
 
 import javax.jcr.Node;
 import javax.jcr.Property;
@@ -30,15 +33,18 @@
 
     private static final Logger log = Logger.getLogger(FilteredPropertyIterator.class);
 
-    private String[] props;
+    private QName[] props;
 
     private Node node;
 
+    private NamespaceResolver resolver;
+
     private int propIndex;
 
-    FilteredPropertyIterator(String[] props, Node node) {
+    FilteredPropertyIterator(QName[] props, Node node, NamespaceResolver resolver) {
         this.props = props;
         this.node = node;
+        this.resolver = resolver;
     }
 
     public Property nextProperty() {
@@ -46,11 +52,14 @@
             throw new NoSuchElementException();
         }
         try {
-            return node.getProperty(props[propIndex++]);
+            return node.getProperty(props[propIndex++].toJCRName(resolver));
         } catch (RepositoryException e) {
             // FIXME find better error handling
             log.error("Exception retrieving property with name: "
                     + props[propIndex - 1]);
+            throw new NoSuchElementException();
+        } catch (NoPrefixDeclaredException e) {
+            log.error("Exception resolving property name: " + e.toString());
             throw new NoSuchElementException();
         }
     }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LuceneQueryBuilder.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LuceneQueryBuilder.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LuceneQueryBuilder.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LuceneQueryBuilder.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LuceneQueryBuilder.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/LuceneQueryBuilder.java	Thu Jan 20 07:10:22 2005
@@ -97,17 +97,16 @@
     public Object visit(QueryRootNode node, Object data) {
         BooleanQuery root = new BooleanQuery();
 
-        String[] props = node.getSelectProperties();
+        QName[] props = node.getSelectProperties();
         for (int i = 0; i < props.length; i++) {
-            String prop = props[i];
             try {
-                prop = nsMappings.translatePropertyName(prop, session.getNamespaceResolver());
-            } catch (IllegalNameException e) {
-                exceptions.add(e);
-            } catch (UnknownPrefixException e) {
+                String prop = props[i].toJCRName(nsMappings);
+                // @todo really search nodes that have non null values?
+                root.add(new MatchAllQuery(prop), true, false);
+            } catch (NoPrefixDeclaredException e) {
+                // should never happen actually. prefixes are dynamically created
                 exceptions.add(e);
             }
-            root.add(new MatchAllQuery(prop), true, false);
         }
 
         Query wrapped = root;
@@ -160,30 +159,25 @@
     }
 
     public Object visit(ExactQueryNode node, Object data) {
-        String field = node.getPropertyName();
+        String field = "";
+        String value = "";
         try {
-            field = nsMappings.translatePropertyName(node.getPropertyName(),
-                    session.getNamespaceResolver());
-        } catch (IllegalNameException e) {
-            exceptions.add(e);
-        } catch (UnknownPrefixException e) {
-            exceptions.add(e);
+            field = node.getPropertyName().toJCRName(nsMappings);
+            value = node.getValue().toJCRName(nsMappings);
+        } catch (NoPrefixDeclaredException e) {
+            // will never happen, prefixes are created when unknown
         }
-        String value = node.getValue();
         return new TermQuery(new Term(field, value));
     }
 
     public Object visit(NodeTypeQueryNode node, Object data) {
-        String field = node.getPropertyName();
+        String field = "";
         List values = new ArrayList();
         try {
-            field = nsMappings.getPrefix(NodeTypeRegistry.JCR_PRIMARY_TYPE.getNamespaceURI())
-                    + ":" + NodeTypeRegistry.JCR_PRIMARY_TYPE.getLocalName();
-
-            values.add(nsMappings.translatePropertyName(node.getValue(),
-                    session.getNamespaceResolver()));
+            field = NodeTypeRegistry.JCR_PRIMARY_TYPE.toJCRName(nsMappings);
+            values.add(node.getValue().toJCRName(nsMappings));
             NodeTypeManager ntMgr = session.getWorkspace().getNodeTypeManager();
-            NodeType base = ntMgr.getNodeType(node.getValue());
+            NodeType base = ntMgr.getNodeType(node.getValue().toJCRName(session.getNamespaceResolver()));
             NodeTypeIterator allTypes = ntMgr.getAllNodeTypes();
             while (allTypes.hasNext()) {
                 NodeType nt = allTypes.nextNodeType();
@@ -197,6 +191,9 @@
             exceptions.add(e);
         } catch (UnknownPrefixException e) {
             exceptions.add(e);
+        } catch (NoPrefixDeclaredException e) {
+            // should never happen
+            exceptions.add(e);
         } catch (RepositoryException e) {
             exceptions.add(e);
         }
@@ -275,7 +272,7 @@
     }
 
     public Object visit(LocationStepQueryNode node, Object data) {
-        if (node.getNameTest() != null && node.getNameTest().length() == 0) {
+        if (node.getNameTest() != null && node.getNameTest().getLocalName().length() == 0) {
             // select root node
             return new TermQuery(new Term(FieldNames.PARENT, ""));
         }
@@ -296,12 +293,10 @@
         TermQuery nameTest = null;
         if (node.getNameTest() != null) {
             try {
-                String internalName = nsMappings.translatePropertyName(node.getNameTest(),
-                        session.getNamespaceResolver());
+                String internalName = node.getNameTest().toJCRName(nsMappings);
                 nameTest = new TermQuery(new Term(FieldNames.LABEL, internalName));
-            } catch (IllegalNameException e) {
-                exceptions.add(e);
-            } catch (UnknownPrefixException e) {
+            } catch (NoPrefixDeclaredException e) {
+                // should never happen
                 exceptions.add(e);
             }
         }
@@ -357,13 +352,11 @@
                         + node.getType());
         }
 
-        String field = node.getProperty();
+        String field = "";
         try {
-            field = nsMappings.translatePropertyName(node.getProperty(),
-                    session.getNamespaceResolver());
-        } catch (IllegalNameException e) {
-            exceptions.add(e);
-        } catch (UnknownPrefixException e) {
+            field = node.getProperty().toJCRName(nsMappings);
+        } catch (NoPrefixDeclaredException e) {
+            // should never happen
             exceptions.add(e);
         }
 
@@ -381,8 +374,11 @@
                 query = new RangeQuery(null, new Term(field, stringValue), true);
                 break;
             case Constants.OPERATION_LIKE:	// LIKE
-                // @todo use MatchAllQuery if stringValue is "*" (or "%" ?)
-                query = new WildcardQuery(new Term(field, stringValue));
+                if (stringValue.equals("%")) {
+                    query = new MatchAllQuery(field);
+                } else {
+                    query = new WildcardQuery(new Term(field, stringValue));
+                }
                 break;
             case Constants.OPERATION_LT:	// <
                 query = new RangeQuery(null, new Term(field, stringValue), false);

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/MatchAllQuery.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/MatchAllQuery.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/MatchAllQuery.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/MatchAllQuery.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/MatchAllQuery.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/MatchAllQuery.java	Thu Jan 20 07:10:22 2005
@@ -53,12 +53,12 @@
     }
 
     /**
-     * Returns the String "*".
+     * Returns the String "%".
      *
      * @param field default field for the query.
-     * @return the String "*".
+     * @return the String "%".
      */
     public String toString(String field) {
-        return "*";
+        return "%";
     }
 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/NodeIndexer.java	Thu Jan 20 07:10:22 2005
@@ -41,7 +41,7 @@
 /**
  * Creates a lucene <code>Document</code> object from a {@link javax.jcr.Node}.
  *
- * @todo add support for indexing of nt:resource. e.g. when mime type is text/*
+ * todo add support for indexing of nt:resource. e.g. when mime type is text/*
  */
 class NodeIndexer {
 

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PropertyIteratorImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PropertyIteratorImpl.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PropertyIteratorImpl.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PropertyIteratorImpl.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PropertyIteratorImpl.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/PropertyIteratorImpl.java	Thu Jan 20 07:10:22 2005
@@ -17,6 +17,8 @@
 package org.apache.jackrabbit.core.search.lucene;
 
 import org.apache.log4j.Logger;
+import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.NamespaceResolver;
 
 import javax.jcr.NodeIterator;
 import javax.jcr.Property;
@@ -30,18 +32,21 @@
 
     private static final Logger log = Logger.getLogger(PropertyIteratorImpl.class);
 
-    private String[] props;
+    private QName[] props;
 
     private NodeIterator nodes;
 
+    private NamespaceResolver resolver;
+
     private Property next;
 
     private PropertyIterator currentProps;
 
     private long pos;
 
-    PropertyIteratorImpl(String[] props, NodeIterator nodes) {
+    PropertyIteratorImpl(QName[] props, NodeIterator nodes, NamespaceResolver resolver) {
         this.nodes = nodes;
+        this.resolver = resolver;
 
         if (props != null && props.length > 0) {
             this.props = props;
@@ -104,7 +109,7 @@
             // try to get next PropertyIterator
             if (nodes.hasNext()) {
                 if (props != null) {
-                    currentProps = new FilteredPropertyIterator(props, nodes.nextNode());
+                    currentProps = new FilteredPropertyIterator(props, nodes.nextNode(), resolver);
                 } else {
                     currentProps = nodes.nextNode().getProperties();
                 }

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryImpl.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryImpl.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryImpl.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryImpl.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryImpl.java	Thu Jan 20 07:10:22 2005
@@ -146,12 +146,12 @@
         // by default. this contrasts to standard sql semantics
         // where default is ascending.
         boolean[] orderSpecs = null;
-        String[] orderProperties = null;
+        QName[] orderProperties = null;
         if (orderNode != null) {
             orderProperties = orderNode.getOrderByProperties();
             orderSpecs = orderNode.getOrderBySpecs();
         } else {
-            orderProperties = new String[0];
+            orderProperties = new QName[0];
             orderSpecs = new boolean[0];
         }
 
@@ -177,7 +177,8 @@
         // return QueryResult
         return new QueryResultImpl(itemMgr,
                 (String[]) uuids.toArray(new String[uuids.size()]),
-                root.getSelectProperties());
+                root.getSelectProperties(),
+                session.getNamespaceResolver());
     }
 
     public String getStatement() {

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryResultImpl.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryResultImpl.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryResultImpl.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryResultImpl.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryResultImpl.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/QueryResultImpl.java	Thu Jan 20 07:10:22 2005
@@ -17,6 +17,8 @@
 package org.apache.jackrabbit.core.search.lucene;
 
 import org.apache.jackrabbit.core.ItemManager;
+import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.NamespaceResolver;
 import org.apache.log4j.Logger;
 
 import javax.jcr.NodeIterator;
@@ -35,14 +37,18 @@
 
     private final String[] uuids;
 
-    private final String[] selectProps;
+    private final QName[] selectProps;
+
+    private final NamespaceResolver resolver;
 
     public QueryResultImpl(ItemManager itemMgr,
                            String[] uuids,
-                           String[] selectProps) {
+                           QName[] selectProps,
+                           NamespaceResolver resolver) {
         this.uuids = uuids;
         this.itemMgr = itemMgr;
         this.selectProps = selectProps;
+        this.resolver = resolver;
     }
 
     /**
@@ -50,7 +56,8 @@
      */
     public PropertyIterator getProperties() throws RepositoryException {
         return new PropertyIteratorImpl(selectProps,
-                new NodeIteratorImpl(itemMgr, uuids));
+                new NodeIteratorImpl(itemMgr, uuids),
+                resolver);
     }
 
     /**

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/SearchIndex.java	Thu Jan 20 07:10:22 2005
@@ -23,6 +23,7 @@
 import org.apache.jackrabbit.core.state.NodeState;
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.ItemManager;
+import org.apache.jackrabbit.core.QName;
 import org.apache.log4j.Logger;
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.standard.StandardAnalyzer;
@@ -205,7 +206,7 @@
     }
 
     Hits executeQuery(Query query,
-                             String[] orderProps,
+                             QName[] orderProps,
                              boolean[] orderSpecs) throws IOException {
         try {
             readWriteLock.readLock().acquire();

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/WildcardTermEnum.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/WildcardTermEnum.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/WildcardTermEnum.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/WildcardTermEnum.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/WildcardTermEnum.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/WildcardTermEnum.java	Thu Jan 20 07:10:22 2005
@@ -63,7 +63,7 @@
     private Pattern createRegexp(String likePattern) {
         // - escape all non alphabetic characters
         // - escape constructs like \<alphabetic char> into \\<alphabetic char>
-        // - replace non escaped ? _ * % into . and .*
+        // - replace non escaped _ % into . and .*
         StringBuffer regexp = new StringBuffer();
         boolean escaped = false;
         for (int i = 0; i < likePattern.length(); i++) {
@@ -88,11 +88,9 @@
                         escaped = false;
                     } else {
                         switch (likePattern.charAt(i)) {
-                            case '?':
                             case '_':
                                 regexp.append('.');
                                 break;
-                            case '*':
                             case '%':
                                 regexp.append(".*");
                                 break;

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTIdentifier.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTIdentifier.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTIdentifier.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTIdentifier.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTIdentifier.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTIdentifier.java	Thu Jan 20 07:10:22 2005
@@ -16,9 +16,11 @@
  */
 package org.apache.jackrabbit.core.search.sql;
 
+import org.apache.jackrabbit.core.QName;
+
 public class ASTIdentifier extends SimpleNode {
 
-    private String name;
+    private QName name;
 
     public ASTIdentifier(int id) {
     super(id);
@@ -28,11 +30,11 @@
     super(p, id);
   }
 
-    public void setName(String name) {
+    public void setName(QName name) {
         this.name = name;
     }
 
-    public String getName() {
+    public QName getName() {
         return name;
     }
 

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTPredicate.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTPredicate.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTPredicate.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTPredicate.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTPredicate.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTPredicate.java	Thu Jan 20 07:10:22 2005
@@ -16,16 +16,20 @@
  */
 package org.apache.jackrabbit.core.search.sql;
 
+import org.apache.jackrabbit.core.QName;
+
 public class ASTPredicate extends SimpleNode {
 
     private int operationType;
 
     private boolean negate = false;
 
-    private String identifier;
+    private QName identifier;
 
     private String identifierOperand;
 
+    private String escapeString;
+
   public ASTPredicate(int id) {
     super(id);
   }
@@ -50,11 +54,11 @@
         return this.negate;
     }
 
-    public void setIdentifier(String identifier) {
+    public void setIdentifier(QName identifier) {
         this.identifier = identifier;
     }
 
-    public String getIdentifier() {
+    public QName getIdentifier() {
         return identifier;
     }
 
@@ -64,6 +68,14 @@
 
     public String getIdentifierOperand() {
         return identifierOperand;
+    }
+
+    public void setEscapeString(String esc) {
+        this.escapeString = esc;
+    }
+
+    public String getEscapeString() {
+        return escapeString;
     }
 
   /** Accept the visitor. **/

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/JCRSQLQueryBuilder.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/JCRSQLQueryBuilder.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/JCRSQLQueryBuilder.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/JCRSQLQueryBuilder.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/JCRSQLQueryBuilder.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/JCRSQLQueryBuilder.java	Thu Jan 20 07:10:22 2005
@@ -33,6 +33,9 @@
 import org.apache.jackrabbit.core.QName;
 import org.apache.jackrabbit.core.NamespaceRegistryImpl;
 import org.apache.jackrabbit.core.NoPrefixDeclaredException;
+import org.apache.jackrabbit.core.IllegalNameException;
+import org.apache.jackrabbit.core.UnknownPrefixException;
+import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.log4j.Logger;
 
 import javax.jcr.query.InvalidQueryException;
@@ -60,7 +63,7 @@
     /**
      * QName for jcr:path
      */
-    private static final QName JCR_PATH = new QName(NamespaceRegistryImpl.NS_JCR_URI, "path");
+    static final QName JCR_PATH = new QName(NamespaceRegistryImpl.NS_JCR_URI, "path");
 
     /** The root node of the sql query syntax tree */
     private final ASTQuery stmt;
@@ -68,27 +71,25 @@
     /** The root query node */
     private QueryRootNode root;
 
+    /** To resolve QNames */
+    private NamespaceResolver resolver;
+
     /** Query node to gather the constraints defined in the WHERE clause */
     private final AndQueryNode constraintNode = new AndQueryNode(null);
 
-    /**
-     * The resolved jcr:path QName using the NamespaceResolver passed in the
-     * constructor.
-     */
-    private final String jcrPathResolved;
+    public JCRSQLQueryBuilder() {
+        stmt = null;
+    }
 
     /**
      * Creates a new <code>JCRSQLQueryBuilder</code>.
      * @param statement the root node of the SQL syntax tree.
      * @param resolver a namespace resolver to use for names in the
      *   <code>statement</code>.
-     * @throws NoPrefixDeclaredException if a prefix in the statement cannot
-     *   be resolved.
      */
-    private JCRSQLQueryBuilder(ASTQuery statement, NamespaceResolver resolver)
-            throws NoPrefixDeclaredException {
+    private JCRSQLQueryBuilder(ASTQuery statement, NamespaceResolver resolver) {
         this.stmt = statement;
-        jcrPathResolved = JCR_PATH.toJCRName(resolver);
+        this.resolver = resolver;
     }
 
     /**
@@ -101,16 +102,29 @@
     public static QueryRootNode createQuery(String statement, NamespaceResolver resolver)
             throws InvalidQueryException {
         try {
-            JCRSQLQueryBuilder builder = new JCRSQLQueryBuilder(JCRSQLParser.parse(statement), resolver);
+            JCRSQLQueryBuilder builder = new JCRSQLQueryBuilder(JCRSQLParser.parse(statement, resolver), resolver);
             return builder.getRootNode();
         } catch (ParseException e) {
             throw new InvalidQueryException(e.getMessage());
-        } catch (NoPrefixDeclaredException e) {
+        } catch (IllegalArgumentException e) {
             throw new InvalidQueryException(e.getMessage());
         }
     }
 
     /**
+     * Creates a String representation of the query node tree in SQL syntax.
+     * @param root the root of the query node tree.
+     * @param resolver to resolve QNames.
+     * @return a String representation of the query node tree.
+     * @throws InvalidQueryException if the query node tree cannot be converted
+     *   into a String representation due to restrictions in SQL.
+     */
+    public static String toString(QueryRootNode root, NamespaceResolver resolver)
+            throws InvalidQueryException {
+        return QueryFormat.toString(root, resolver);
+    }
+
+    /**
      * Parses the statement and returns the root node of the <code>QueryNode</code>
      * tree.
      * @return the root node of the <code>QueryNode</code> tree.
@@ -139,7 +153,7 @@
         // use //* if no path has been set
         PathQueryNode pathNode = root.getLocationNode();
         if (pathNode.getPathSteps().length == 0) {
-            pathNode.addPathStep(new LocationStepQueryNode(pathNode, "", false));
+            pathNode.addPathStep(new LocationStepQueryNode(pathNode, new QName("", ""), false));
             pathNode.addPathStep(new LocationStepQueryNode(pathNode, null, true));
         }
 
@@ -168,10 +182,16 @@
 
         return node.childrenAccept(new DefaultParserVisitor() {
             public Object visit(ASTIdentifier node, Object data) {
-                // node is either primary or mixin node type
-                NodeTypeQueryNode nodeType
-                        = new NodeTypeQueryNode(constraintNode, node.getName());
-                constraintNode.addOperand(nodeType);
+                try {
+                    if (!node.getName().equals(NodeTypeRegistry.NT_BASE.toJCRName(resolver))) {
+                        // node is either primary or mixin node type
+                        NodeTypeQueryNode nodeType
+                                = new NodeTypeQueryNode(constraintNode, node.getName());
+                        constraintNode.addOperand(nodeType);
+                    }
+                } catch (NoPrefixDeclaredException e) {
+                    throw new IllegalArgumentException("No prefix declared for name: " + node.getName());
+                }
                 return data;
             }
         }, root);
@@ -191,18 +211,18 @@
         int type = node.getOperationType();
         QueryNode predicateNode = null;
 
-        String identifier = ((ASTIdentifier) node.children[0]).getName();
-        if (identifier.equals(jcrPathResolved)) {
-            if (node.children[1] instanceof ASTIdentifier) {
-                // simply ignore, this is a join of a mixin node type
-            } else {
-                createPathQuery(((ASTLiteral) node.children[1]).getValue());
+        try {
+            QName identifier = ((ASTIdentifier) node.children[0]).getName();
+            if (identifier.equals(JCR_PATH)) {
+                if (node.children[1] instanceof ASTIdentifier) {
+                    // simply ignore, this is a join of a mixin node type
+                } else {
+                    createPathQuery(((ASTLiteral) node.children[1]).getValue());
+                }
+                // done
+                return data;
             }
-            // done
-            return data;
-        }
 
-        try {
             if (type == Constants.OPERATION_BETWEEN) {
                 AndQueryNode between = new AndQueryNode(parent);
                 RelationQueryNode rel = createRelationQueryNode(between,
@@ -222,11 +242,27 @@
             } else if (type == Constants.OPERATION_GE
                     || type == Constants.OPERATION_GT
                     || type == Constants.OPERATION_LE
-                    || type == Constants.OPERATION_LIKE
                     || type == Constants.OPERATION_LT
                     || type == Constants.OPERATION_NE) {
                 predicateNode = createRelationQueryNode(parent,
                         identifier, type, (ASTLiteral) node.children[1]);
+            } else if (type == Constants.OPERATION_LIKE) {
+                ASTLiteral pattern = (ASTLiteral) node.children[1];
+                if (node.getEscapeString() != null) {
+                    if (node.getEscapeString().length() == 1) {
+                        // backslash is the escape character we use internally
+                        pattern.setValue(translateEscaping(pattern.getValue(), node.getEscapeString().charAt(0), '\\'));
+                    } else {
+                        throw new IllegalArgumentException("ESCAPE string value must have length 1: '" + node.getEscapeString() + "'");
+                    }
+                } else {
+                    // no escape character specified.
+                    // if the pattern contains any backslash characters we need
+                    // to escape them.
+                    pattern.setValue(pattern.getValue().replaceAll("\\\\", "\\\\\\\\"));
+                }
+                predicateNode = createRelationQueryNode(parent,
+                        identifier, type, pattern);
             } else if (type == Constants.OPERATION_IN) {
                 OrQueryNode in = new OrQueryNode(parent);
                 for (int i = 1; i < node.children.length; i++) {
@@ -238,14 +274,12 @@
             } else if (type == Constants.OPERATION_NULL) {
                 ASTLiteral star = new ASTLiteral(JCRSQLParserTreeConstants.JJTLITERAL);
                 star.setType(Constants.TYPE_STRING);
-                star.setValue("*");
+                star.setValue("%");
                 predicateNode = createRelationQueryNode(parent,
                         identifier, Constants.OPERATION_LIKE, star);
             }
-        } catch (IllegalArgumentException e) {
-            log.error(e.toString());
         } catch (ArrayIndexOutOfBoundsException e) {
-            log.error("Too few arguments");
+            throw new IllegalArgumentException("Too few arguments in predicate");
         }
 
         if (predicateNode != null) {
@@ -305,7 +339,9 @@
     public Object visit(ASTOrderByClause node, Object data) {
         QueryRootNode root = (QueryRootNode) data;
 
+        // list of QNames
         final List identifiers = new ArrayList();
+
         // collect identifiers
         node.childrenAccept(new DefaultParserVisitor() {
             public Object visit(ASTIdentifier node, Object data) {
@@ -314,7 +350,7 @@
             }
         }, root);
 
-        String[] props = (String[]) identifiers.toArray(new String[identifiers.size()]);
+        QName[] props = (QName[]) identifiers.toArray(new QName[identifiers.size()]);
         boolean[] orders = new boolean[props.length];
         root.setOrderNode(new OrderQueryNode(root, props, orders));
         return root;
@@ -339,7 +375,7 @@
      * to its type. E.g. a malformed String representation of a date.
      */
     private RelationQueryNode createRelationQueryNode(QueryNode parent,
-                                                      String propertyName,
+                                                      QName propertyName,
                                                       int operationType,
                                                       ASTLiteral literal)
             throws IllegalArgumentException {
@@ -359,8 +395,6 @@
                 long l = Long.parseLong(stringValue);
                 node = new RelationQueryNode(parent, propertyName, l, operationType);
             } else if (literal.getType() == Constants.TYPE_STRING) {
-                // @todo convert % and _ into * and ? if opType is LIKE
-                // @todo take care of escaping!
                 node = new RelationQueryNode(parent, propertyName, stringValue, operationType);
             } else if (literal.getType() == Constants.TYPE_TIMESTAMP) {
                 Calendar c = ISO8601.parse(stringValue);
@@ -390,7 +424,7 @@
             if (names[i].length() == 0) {
                 if (i == 0) {
                     // root
-                    pathNode.addPathStep(new LocationStepQueryNode(pathNode, "", false));
+                    pathNode.addPathStep(new LocationStepQueryNode(pathNode, new QName("", ""), false));
                 } else {
                     // descendant '//'
                     // FIXME this is not possible
@@ -403,26 +437,86 @@
                     // contains index
                     name = names[i].substring(0, idx);
                     String suffix = names[i].substring(idx);
-                    try {
-                        index = Integer.parseInt(suffix.substring(1, suffix.length() - 1));
-                    } catch (NumberFormatException e) {
-                        log.warn("Unable to parse index for path element: " + names[i]);
+                    String indexStr = suffix.substring(1, suffix.length() - 1);
+                    if (indexStr.equals("%")) {
+                        // select all same name siblings
+                        index = 0;
+                    } else {
+                        try {
+                            index = Integer.parseInt(indexStr);
+                        } catch (NumberFormatException e) {
+                            log.warn("Unable to parse index for path element: " + names[i]);
+                        }
                     }
                 } else {
                     // no index
                     name = names[i];
+                    // in SQL this means index 1
+                    index = 1;
                 }
                 if (name.equals("%")) {
                     name = null;
                 }
+                QName qName = null;
+                if (name != null) {
+                    try {
+                        qName = QName.fromJCRName(name, resolver);
+                    } catch (IllegalNameException e) {
+                        throw new IllegalArgumentException("Illegal name: " + name);
+                    } catch (UnknownPrefixException e) {
+                        throw new IllegalArgumentException("Unknown prefix: " + name);
+                    }
+                }
                 // @todo how to specify descendant-or-self?
-                LocationStepQueryNode step = new LocationStepQueryNode(pathNode, name, false);
+                LocationStepQueryNode step = new LocationStepQueryNode(pathNode, qName, false);
                 if (index > 0) {
                     step.setIndex(index);
                 }
                 pathNode.addPathStep(step);
             }
         }
+    }
+
+    /**
+     * Translates a pattern using the escape character <code>from</code> into
+     * a pattern using the escape character <code>to</code>.
+     * @param pattern the pattern to translate
+     * @param from the currently used escape character.
+     * @param to the new escape character to use.
+     * @return the new pattern using the escape character <code>to</code>.
+     */
+    private static String translateEscaping(String pattern, char from, char to) {
+        // if escape characters are the same OR pattern does not contain any
+        // escape characters -> simply return pattern as is.
+        if (from == to || (pattern.indexOf(from) < 0 && pattern.indexOf(to) < 0)) {
+            return pattern;
+        }
+        StringBuffer translated = new StringBuffer(pattern.length());
+        boolean escaped = false;
+        for (int i = 0; i < pattern.length(); i++) {
+            if (pattern.charAt(i) == from) {
+                if (escaped) {
+                    translated.append(from);
+                    escaped = false;
+                } else {
+                    escaped = true;
+                }
+            } else if (pattern.charAt(i) == to) {
+                if (escaped) {
+                    translated.append(to).append(to);
+                    escaped = false;
+                } else {
+                    translated.append(to).append(to);
+                }
+            } else {
+                if (escaped) {
+                    translated.append(to);
+                    escaped = false;
+                }
+                translated.append(pattern.charAt(i));
+            }
+        }
+        return translated.toString();
     }
 
 }

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/QueryFormat.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/QueryFormat.java?view=auto&rev=125778
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/QueryFormat.java	Thu Jan 20 07:10:22 2005
@@ -0,0 +1,408 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.search.sql;
+
+import org.apache.jackrabbit.core.search.QueryNodeVisitor;
+import org.apache.jackrabbit.core.search.QueryRootNode;
+import org.apache.jackrabbit.core.search.OrQueryNode;
+import org.apache.jackrabbit.core.search.AndQueryNode;
+import org.apache.jackrabbit.core.search.NotQueryNode;
+import org.apache.jackrabbit.core.search.ExactQueryNode;
+import org.apache.jackrabbit.core.search.NodeTypeQueryNode;
+import org.apache.jackrabbit.core.search.RangeQueryNode;
+import org.apache.jackrabbit.core.search.TextsearchQueryNode;
+import org.apache.jackrabbit.core.search.PathQueryNode;
+import org.apache.jackrabbit.core.search.LocationStepQueryNode;
+import org.apache.jackrabbit.core.search.RelationQueryNode;
+import org.apache.jackrabbit.core.search.OrderQueryNode;
+import org.apache.jackrabbit.core.search.QueryNode;
+import org.apache.jackrabbit.core.search.Constants;
+import org.apache.jackrabbit.core.NamespaceResolver;
+import org.apache.jackrabbit.core.NoPrefixDeclaredException;
+import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
+
+import javax.jcr.query.InvalidQueryException;
+import javax.jcr.util.ISO8601;
+import java.util.Calendar;
+import java.util.TimeZone;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Iterator;
+
+/**
+ * Implements the query node tree serialization into a String.
+ */
+class QueryFormat implements QueryNodeVisitor, Constants {
+
+    /** Will be used to resolve QNames */
+    private final NamespaceResolver resolver;
+
+    /** The String representation of the query node tree */
+    private String statement;
+
+    /** List of exception objects created while creating the SQL string */
+    private List exceptions = new ArrayList();
+
+    /** List of node types */
+    private List nodeTypes = new ArrayList();
+
+    private QueryFormat(QueryRootNode root, NamespaceResolver resolver)
+            throws InvalidQueryException {
+        this.resolver = resolver;
+        statement = root.accept(this, new StringBuffer()).toString();
+        if (exceptions.size() > 0) {
+            Exception e = (Exception) exceptions.get(0);
+            throw new InvalidQueryException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * Creates a SQL <code>String</code> representation of the QueryNode tree
+     * argument <code>root</code>.
+     * @param root the query node tree.
+     * @param resolver to resolve QNames.
+     * @return the SQL string representation of the QueryNode tree.
+     * @throws InvalidQueryException the query node tree cannot be represented
+     *   as a SQL <code>String</code>.
+     */
+    public static String toString(QueryRootNode root, NamespaceResolver resolver)
+            throws InvalidQueryException {
+        return new QueryFormat(root, resolver).toString();
+    }
+
+    /**
+     * Returns the string representation.
+     * @return the string representation.
+     */
+    public String toString() {
+        return statement;
+    }
+
+    //-------------< QueryNodeVisitor interface >-------------------------------
+
+    public Object visit(QueryRootNode node, Object data) {
+        StringBuffer sb = (StringBuffer) data;
+        try {
+            sb.append("SELECT");
+
+            QName[] selectProps = node.getSelectProperties();
+            if (selectProps.length == 0) {
+                sb.append(" *");
+            } else {
+                String comma = "";
+                for (int i = 0; i < selectProps.length; i++) {
+                    sb.append(comma).append(" ");
+                    appendName(selectProps[i], resolver, sb);
+                    comma = ",";
+                }
+            }
+
+            sb.append(" FROM");
+
+            // node type restrictions are within predicates of location nodes
+            // therefore we write the where clause first to a temp string to
+            // collect the node types.
+            StringBuffer tmp = new StringBuffer();
+            LocationStepQueryNode[] steps = node.getLocationNode().getPathSteps();
+            QueryNode[] predicates = steps[steps.length - 1].getPredicates();
+            String and = "";
+            for (int i = 0; i < predicates.length; i++) {
+                if (i == 0) {
+                    tmp.append(" WHERE ");
+                }
+                tmp.append(and);
+                predicates[i].accept(this, tmp);
+                and = " AND ";
+            }
+
+            // node types have been collected by now
+            String comma = "";
+            int ntCount = 0;
+            for (Iterator it = nodeTypes.iterator(); it.hasNext(); ntCount++) {
+                QName nt = (QName) it.next();
+                sb.append(comma).append(" ");
+                appendName(nt, resolver, sb);
+                comma = ",";
+            }
+
+            if (ntCount == 0) {
+                sb.append(" ");
+                sb.append(NodeTypeRegistry.NT_BASE.toJCRName(resolver));
+            }
+
+            // append WHERE clause
+            sb.append(tmp.toString());
+
+            if (steps.length == 2
+                    && steps[1].getIncludeDescendants()
+                    && steps[1].getNameTest() == null) {
+                // then this query selects all paths
+            } else {
+                if (predicates.length > 0) {
+                    sb.append(" AND ");
+                } else {
+                    sb.append(" WHERE ");
+                }
+                node.getLocationNode().accept(this, sb);
+            }
+        } catch (NoPrefixDeclaredException e) {
+            exceptions.add(e);
+        }
+
+        if (node.getOrderNode() != null) {
+            node.getOrderNode().accept(this, sb);
+        }
+
+        return sb;
+    }
+
+    public Object visit(OrQueryNode node, Object data) {
+        StringBuffer sb = (StringBuffer) data;
+        boolean bracket = false;
+        if (node.getParent() instanceof LocationStepQueryNode
+                || node.getParent() instanceof AndQueryNode
+                || node.getParent() instanceof NotQueryNode) {
+            bracket = true;
+        }
+        if (bracket) {
+            sb.append("(");
+        }
+        String or = "";
+        QueryNode[] operands = node.getOperands();
+        for (int i = 0; i < operands.length; i++) {
+            sb.append(or);
+            operands[i].accept(this, sb);
+            or = " OR ";
+        }
+        if (bracket) {
+            sb.append(")");
+        }
+        return sb;
+    }
+
+    public Object visit(AndQueryNode node, Object data) {
+        StringBuffer sb = (StringBuffer) data;
+        boolean bracket = false;
+        if (node.getParent() instanceof NotQueryNode) {
+            bracket = true;
+        }
+        if (bracket) {
+            sb.append("(");
+        }
+        String and = "";
+        QueryNode[] operands = node.getOperands();
+        for (int i = 0; i < operands.length; i++) {
+            sb.append(and);
+            int len = sb.length();
+            operands[i].accept(this, sb);
+            // check if something has been written at all
+            // might have been a node type query node
+            if (sb.length() - len > 0) {
+                and = " AND ";
+            } else {
+                and = "";
+            }
+        }
+        if (bracket) {
+            sb.append(")");
+        }
+        return sb;
+    }
+
+    public Object visit(NotQueryNode node, Object data) {
+        StringBuffer sb = (StringBuffer) data;
+        QueryNode[] operands = node.getOperands();
+        if (operands.length > 0) {
+                sb.append("NOT ");
+                operands[0].accept(this, sb);
+        }
+        return sb;
+    }
+
+    public Object visit(ExactQueryNode node, Object data) {
+        StringBuffer sb = (StringBuffer) data;
+        try {
+            appendName(node.getPropertyName(), resolver, sb);
+        } catch (NoPrefixDeclaredException e) {
+            exceptions.add(e);
+        }
+        sb.append("='").append(node.getValue()).append("'");
+        return sb;
+    }
+
+    public Object visit(NodeTypeQueryNode node, Object data) {
+        nodeTypes.add(node.getValue());
+        return data;
+    }
+
+    public Object visit(RangeQueryNode node, Object data) {
+        return data;
+    }
+
+    public Object visit(TextsearchQueryNode node, Object data) {
+        StringBuffer sb = (StringBuffer) data;
+        // escape quote
+        String query = node.getQuery().replaceAll("'", "''");
+        sb.append("CONTAINS('").append(query).append("')");
+        return sb;
+    }
+
+    public Object visit(PathQueryNode node, Object data) {
+        StringBuffer sb = (StringBuffer) data;
+        try {
+            sb.append(JCRSQLQueryBuilder.JCR_PATH.toJCRName(resolver));
+            sb.append(" LIKE '");
+            LocationStepQueryNode[] steps = node.getPathSteps();
+            for (int i = 0; i < steps.length; i++) {
+                if (steps[i].getNameTest() == null
+                        || steps[i].getNameTest().getLocalName().length() > 0) {
+                    sb.append('/');
+                }
+                steps[i].accept(this, sb);
+            }
+            sb.append('\'');
+        } catch (NoPrefixDeclaredException e) {
+            exceptions.add(e);
+        }
+        return sb;
+    }
+
+    public Object visit(LocationStepQueryNode node, Object data) {
+        StringBuffer sb = (StringBuffer) data;
+        if (node.getNameTest() == null) {
+            sb.append("%");
+        } else {
+            if (node.getNameTest().getLocalName().length() > 0) {
+                try {
+                    sb.append(node.getNameTest().toJCRName(resolver));
+                } catch (NoPrefixDeclaredException e) {
+                    exceptions.add(e);
+                }
+                if (node.getIndex() == 0) {
+                    sb.append("[%]");
+                } else if (node.getIndex() == 1) {
+                    // do nothing
+                } else {
+                    sb.append('[').append(node.getIndex()).append(']');
+                }
+            } else {
+                // empty name test indicates root node
+            }
+        }
+        return sb;
+    }
+
+    public Object visit(RelationQueryNode node, Object data) {
+        StringBuffer sb = (StringBuffer) data;
+        try {
+            appendName(node.getProperty(), resolver, sb);
+        } catch (NoPrefixDeclaredException e) {
+            exceptions.add(e);
+        }
+
+        if (node.getOperation() == OPERATION_EQ) {
+            sb.append(" = ");
+        } else if (node.getOperation() == OPERATION_GE) {
+            sb.append(" >= ");
+        } else if (node.getOperation() == OPERATION_GT) {
+            sb.append(" > ");
+        } else if (node.getOperation() == OPERATION_LE) {
+            sb.append(" <= ");
+        } else if (node.getOperation() == OPERATION_LIKE) {
+            sb.append(" LIKE ");
+        } else if (node.getOperation() == OPERATION_LT) {
+            sb.append(" < ");
+        } else if (node.getOperation() == OPERATION_NE) {
+            sb.append(" <> ");
+        } else {
+            exceptions.add(new InvalidQueryException("Invalid operation: " + node.getOperation()));
+        }
+
+
+        if (node.getType() == TYPE_LONG) {
+            sb.append(node.getLongValue());
+        } else if (node.getType() == TYPE_DOUBLE) {
+            sb.append(node.getDoubleValue());
+        } else if (node.getType() == TYPE_STRING) {
+            sb.append("'").append(node.getStringValue().replaceAll("'", "''")).append("'");
+        } else if (node.getType() == TYPE_DATE || node.getType() == TYPE_TIMESTAMP) {
+            Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+            cal.setTime(node.getDateValue());
+            sb.append("TIMESTAMP '").append(ISO8601.format(cal)).append("'");
+        } else {
+            exceptions.add(new InvalidQueryException("Invalid type: " + node.getType()));
+        }
+
+        if (node.getOperation() == OPERATION_LIKE && node.getStringValue().indexOf('\\') > -1) {
+            sb.append(" ESCAPE '\\'");
+        }
+
+        return sb;
+    }
+
+    public Object visit(OrderQueryNode node, Object data) {
+        StringBuffer sb = (StringBuffer) data;
+        sb.append(" ORDER BY");
+        QName[] properties = node.getOrderByProperties();
+        if (properties.length > 0) {
+            try {
+                String comma = "";
+                for (int i = 0; i < properties.length; i++) {
+                    sb.append(comma).append(" ");
+                    appendName(properties[i], resolver, sb);
+                    if (!node.isAscending(i)) {
+                        sb.append(" DESC");
+                    }
+                    comma = ",";
+                }
+            } catch (NoPrefixDeclaredException e) {
+                exceptions.add(e);
+            }
+        } else {
+            sb.append(" SCORE");
+        }
+        return sb;
+    }
+
+    //------------------------< internal >--------------------------------------
+
+    /**
+     * Appends the <code>name</code> to the <code>StringBuffer</code>
+     * <code>b</code> using the <code>NamespaceResolver</code>
+     * <code>resolver</code>. The <code>name</code> is put in double quotes
+     * if the local part of <code>name</code> contains a space character.
+     * @param name the <code>QName</code> to print.
+     * @param resolver to resolve <code>name</code>.
+     * @param b where to output the <code>name</code>.
+     * @throws NoPrefixDeclaredException if <code>name</code> contains a uri
+     *   that is not declared in <code>resolver</code>.
+     */
+    private static void appendName(QName name,
+                                   NamespaceResolver resolver,
+                                   StringBuffer b)
+            throws NoPrefixDeclaredException {
+        boolean quote = name.getLocalName().indexOf(' ') > -1;
+        if (quote) {
+            b.append('"');
+        }
+        b.append(name.toJCRName(resolver));
+        if (quote) {
+            b.append('"');
+        }
+    }
+}

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/ISO9075.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/ISO9075.java?view=auto&rev=125778
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/ISO9075.java	Thu Jan 20 07:10:22 2005
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.search.xpath;
+
+import org.apache.jackrabbit.core.QName;
+import org.apache.xerces.util.XMLChar;
+
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+/**
+ * Implements the encode and decode routines as specified for XML name to SQL
+ * identifier conversion in ISO 9075-14:2003.<br/>
+ * If a character <code>c</code> is not valid at a certain position in an XML 1.0
+ * Name it is encoded in the form: '_x' + hexValueOf(c) + '_'
+ * todo or is it NCName
+ * <p/>
+ * Note that only the local part of a {@link org.apache.jackrabbit.core.QName}
+ * is encoded / decoded. A URI namespace will always be valid and does not
+ * need encoding.
+ */
+public class ISO9075 {
+
+    /** Pattern on an encoded character */
+    private static Pattern ENCODE_PATTERN = Pattern.compile("_x\\p{XDigit}{4}_");
+
+    /** Padding characters */
+    private static char[] PADDING = new char[] {'0', '0', '0'};
+
+    /**
+     * Encodes the local part of <code>name</code> as specified in ISO 9075.
+     * @param name the <code>QName</code> to encode.
+     * @return the encoded <code>QName</code> or <code>name</code> if it does
+     *   not need encoding.
+     */
+    public static QName encode(QName name) {
+        String encoded = encode(name.getLocalName());
+        if (encoded == name.getLocalName()) {
+            return name;
+        } else {
+            return new QName(name.getNamespaceURI(), encoded);
+        }
+    }
+
+    /**
+     * Encodes <code>name</code> as specified in ISO 9075.
+     * @param name the <code>String</code> to encode.
+     * @return the encoded <code>String</code> or <code>name</code> if it does
+     *   not need encoding.
+     */
+    public static String encode(String name) {
+        // quick check for root node name
+        if (name.length() == 0) {
+            return name;
+        }
+        if (XMLChar.isValidName(name) && name.indexOf("_x") < 0) {
+            // already valid
+            return name;
+        } else {
+            // encode
+            StringBuffer encoded = new StringBuffer();
+            for (int i = 0; i < name.length(); i++) {
+                if (i == 0) {
+                    // first character of name
+                    if (XMLChar.isNameStart(name.charAt(i))) {
+                        if (name.charAt(i) == '_'
+                                && name.length() > (i + 1)
+                                && name.charAt(i + 1) == 'x') {
+                            // '_x' must be encoded
+                            encode('_', encoded);
+                        } else {
+                            encoded.append(name.charAt(i));
+                        }
+                    } else {
+                        // not valid as first character -> encode
+                        encode(name.charAt(i), encoded);
+                    }
+                } else if (!XMLChar.isName(name.charAt(i))) {
+                    encode(name.charAt(i), encoded);
+                } else {
+                    if (name.charAt(i) == '_'
+                            && name.length() > (i + 1)
+                            && name.charAt(i + 1) == 'x') {
+                        // '_x' must be encoded
+                        encode('_', encoded);
+                    } else {
+                        encoded.append(name.charAt(i));
+                    }
+                }
+            }
+            return encoded.toString();
+        }
+    }
+
+    /**
+     * Decodes the <code>name</code>.
+     * @param name the <code>QName</code> to decode.
+     * @return the decoded <code>QName</code>.
+     */
+    public static QName decode(QName name) {
+        String decoded = decode(name.getLocalName());
+        if (decoded == name.getLocalName()) {
+            return name;
+        } else {
+            return new QName(name.getNamespaceURI(), decoded.toString());
+        }
+    }
+
+    /**
+     * Decodes the <code>name</code>.
+     * @param name the <code>String</code> to decode.
+     * @return the decoded <code>String</code>.
+     */
+    public static String decode(String name) {
+        // quick check
+        if (name.indexOf("_x") < 0) {
+            // not encoded
+            return name;
+        }
+        StringBuffer decoded = new StringBuffer();
+        Matcher m = ENCODE_PATTERN.matcher(name);
+        while (m.find()) {
+            m.appendReplacement(decoded, Character.toString((char) Integer.parseInt(m.group().substring(2, 6), 16)));
+        }
+        m.appendTail(decoded);
+        return decoded.toString();
+    }
+
+    //-------------------------< internal >-------------------------------------
+
+    /**
+     * Encodes the character <code>c</code> as a String in the following form:
+     * <code>"_x" + hex value of c + "_"</code>. Where the hex value has always
+     * four digits with possibly leading zeros.
+     * <p/>
+     * Example: ' ' (the space character) is encoded to: _x0020_
+     * @param c the character to encode
+     * @param b the encoded character is appended to <code>StringBuffer</code>
+     *  <code>b</code>.
+     */
+    private static void encode(char c, StringBuffer b) {
+        b.append("_x");
+        String hex = Integer.toHexString(c);
+        b.append(PADDING, 0, 4 - hex.length());
+        b.append(hex);
+        b.append("_");
+    }
+
+}

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/QueryFormat.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/QueryFormat.java?view=auto&rev=125778
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/QueryFormat.java	Thu Jan 20 07:10:22 2005
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.search.xpath;
+
+import org.apache.jackrabbit.core.search.QueryNodeVisitor;
+import org.apache.jackrabbit.core.search.QueryRootNode;
+import org.apache.jackrabbit.core.search.OrQueryNode;
+import org.apache.jackrabbit.core.search.AndQueryNode;
+import org.apache.jackrabbit.core.search.NotQueryNode;
+import org.apache.jackrabbit.core.search.ExactQueryNode;
+import org.apache.jackrabbit.core.search.NodeTypeQueryNode;
+import org.apache.jackrabbit.core.search.RangeQueryNode;
+import org.apache.jackrabbit.core.search.TextsearchQueryNode;
+import org.apache.jackrabbit.core.search.PathQueryNode;
+import org.apache.jackrabbit.core.search.LocationStepQueryNode;
+import org.apache.jackrabbit.core.search.RelationQueryNode;
+import org.apache.jackrabbit.core.search.OrderQueryNode;
+import org.apache.jackrabbit.core.search.QueryNode;
+import org.apache.jackrabbit.core.search.Constants;
+import org.apache.jackrabbit.core.NamespaceResolver;
+import org.apache.jackrabbit.core.NoPrefixDeclaredException;
+import org.apache.jackrabbit.core.QName;
+import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
+
+import javax.jcr.query.InvalidQueryException;
+import javax.jcr.util.ISO8601;
+import java.util.Calendar;
+import java.util.TimeZone;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Implements the query node tree serialization into a String.
+ */
+class QueryFormat implements QueryNodeVisitor, Constants {
+
+    /** Will be used to resolve QNames */
+    private final NamespaceResolver resolver;
+
+    /** The String representation of the query node tree */
+    private String statement;
+
+    /** List of exception objects created while creating the XPath string */
+    private List exceptions = new ArrayList();
+
+    private QueryFormat(QueryRootNode root, NamespaceResolver resolver)
+            throws InvalidQueryException {
+        this.resolver = resolver;
+        statement = root.accept(this, new StringBuffer()).toString();
+        if (exceptions.size() > 0) {
+            Exception e = (Exception) exceptions.get(0);
+            throw new InvalidQueryException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * Creates a XPath <code>String</code> representation of the QueryNode tree
+     * argument <code>root</code>.
+     * @param root the query node tree.
+     * @param resolver to resolve QNames.
+     * @return the XPath string representation of the QueryNode tree.
+     * @throws InvalidQueryException the query node tree cannot be represented
+     *   as a XPath <code>String</code>.
+     */
+    public static String toString(QueryRootNode root, NamespaceResolver resolver)
+            throws InvalidQueryException {
+        return new QueryFormat(root, resolver).toString();
+    }
+
+    /**
+     * Returns the string representation.
+     * @return the string representation.
+     */
+    public String toString() {
+        return statement;
+    }
+
+    //-------------< QueryNodeVisitor interface >-------------------------------
+
+    public Object visit(QueryRootNode node, Object data) {
+        StringBuffer sb = (StringBuffer) data;
+        node.getLocationNode().accept(this, data);
+        if (node.getOrderNode() != null) {
+            node.getOrderNode().accept(this, data);
+        }
+        QName[] selectProps = node.getSelectProperties();
+        if (selectProps.length > 0) {
+            sb.append('/');
+            boolean union = selectProps.length > 1;
+            if (union) {
+                sb.append('(');
+            }
+            String pipe = "";
+            for (int i = 0; i < selectProps.length; i++) {
+                try {
+                    sb.append(pipe);
+                    sb.append('@');
+                    sb.append(ISO9075.encode(selectProps[i]).toJCRName(resolver));
+                    pipe = "|";
+                } catch (NoPrefixDeclaredException e) {
+                    exceptions.add(e);
+                }
+            }
+            if (union) {
+                sb.append(')');
+            }
+        }
+        return data;
+    }
+
+    public Object visit(OrQueryNode node, Object data) {
+        StringBuffer sb = (StringBuffer) data;
+        boolean bracket = false;
+        if (node.getParent() instanceof AndQueryNode) {
+            bracket = true;
+        }
+        if (bracket) {
+            sb.append("(");
+        }
+        String or = "";
+        QueryNode[] operands = node.getOperands();
+        for (int i = 0; i < operands.length; i++) {
+            sb.append(or);
+            operands[i].accept(this, sb);
+            or = " or ";
+        }
+        if (bracket) {
+            sb.append(")");
+        }
+        return sb;
+    }
+
+    public Object visit(AndQueryNode node, Object data) {
+        StringBuffer sb = (StringBuffer) data;
+        String and = "";
+        QueryNode[] operands = node.getOperands();
+        for (int i = 0; i < operands.length; i++) {
+            sb.append(and);
+            operands[i].accept(this, sb);
+            and = " and ";
+        }
+        return sb;
+    }
+
+    public Object visit(NotQueryNode node, Object data) {
+        StringBuffer sb = (StringBuffer) data;
+        QueryNode[] operands = node.getOperands();
+        if (operands.length > 0) {
+            try {
+                sb.append(XPathQueryBuilder.FN_NOT_10.toJCRName(resolver));
+                sb.append("(");
+                operands[0].accept(this, sb);
+                sb.append(")");
+            } catch (NoPrefixDeclaredException e) {
+                exceptions.add(e);
+            }
+        }
+        return sb;
+    }
+
+    public Object visit(ExactQueryNode node, Object data) {
+        StringBuffer sb = (StringBuffer) data;
+        sb.append("@");
+        try {
+            sb.append(ISO9075.encode(node.getPropertyName()).toJCRName(resolver));
+            sb.append("='").append(node.getValue().toJCRName(resolver));
+        } catch (NoPrefixDeclaredException e) {
+            exceptions.add(e);
+        }
+        sb.append("'");
+        return sb;
+    }
+
+    public Object visit(NodeTypeQueryNode node, Object data) {
+        StringBuffer sb = (StringBuffer) data;
+        try {
+            sb.append("@");
+            sb.append(NodeTypeRegistry.JCR_PRIMARY_TYPE.toJCRName(resolver));
+            sb.append("='").append(node.getValue().toJCRName(resolver));
+            sb.append("'");
+        } catch (NoPrefixDeclaredException e) {
+            exceptions.add(e);
+        }
+        return sb;
+    }
+
+    public Object visit(RangeQueryNode node, Object data) {
+        return data;
+    }
+
+    public Object visit(TextsearchQueryNode node, Object data) {
+        StringBuffer sb = (StringBuffer) data;
+        try {
+            sb.append(XPathQueryBuilder.JCRFN_CONTAINS.toJCRName(resolver));
+            sb.append("('");
+            sb.append(node.getQuery().replaceAll("'", "''"));
+            sb.append("')");
+        } catch (NoPrefixDeclaredException e) {
+            exceptions.add(e);
+        }
+        return sb;
+    }
+
+    public Object visit(PathQueryNode node, Object data) {
+        StringBuffer sb = (StringBuffer) data;
+        LocationStepQueryNode[] steps = node.getPathSteps();
+        for (int i = 0; i < steps.length; i++) {
+            if (steps[i].getNameTest() == null
+                    || steps[i].getNameTest().getLocalName().length() > 0) {
+                sb.append('/');
+            }
+            steps[i].accept(this, sb);
+        }
+        return sb;
+    }
+
+    public Object visit(LocationStepQueryNode node, Object data) {
+        StringBuffer sb = (StringBuffer) data;
+        if (node.getIncludeDescendants()) {
+            sb.append('/');
+        }
+        if (node.getNameTest() == null) {
+            sb.append("*");
+        } else {
+            try {
+                sb.append(ISO9075.encode(node.getNameTest()).toJCRName(resolver));
+            } catch (NoPrefixDeclaredException e) {
+                exceptions.add(e);
+            }
+        }
+        if (node.getIndex() > 0) {
+            sb.append('[').append(node.getIndex()).append(']');
+        }
+        QueryNode[] predicates = node.getPredicates();
+        for (int i = 0; i < predicates.length; i++) {
+            sb.append('[');
+            predicates[i].accept(this, sb);
+            sb.append(']');
+        }
+        return sb;
+    }
+
+    public Object visit(RelationQueryNode node, Object data) {
+        StringBuffer sb = (StringBuffer) data;
+        try {
+
+            int propIdx = sb.length();
+            sb.append("@" + ISO9075.encode(node.getProperty()).toJCRName(resolver));
+
+            if (node.getOperation() == OPERATION_EQ) {
+                sb.append(" = ");
+            } else if (node.getOperation() == OPERATION_GE) {
+                sb.append(" >= ");
+            } else if (node.getOperation() == OPERATION_GT) {
+                sb.append(" > ");
+            } else if (node.getOperation() == OPERATION_LE) {
+                sb.append(" <= ");
+            } else if (node.getOperation() == OPERATION_LIKE) {
+                sb.insert(propIdx, XPathQueryBuilder.JCRFN_LIKE.toJCRName(resolver) + "(");
+                sb.append(",");
+            } else if (node.getOperation() == OPERATION_LT) {
+                sb.append(" < ");
+            } else if (node.getOperation() == OPERATION_NE) {
+                sb.append(" != ");
+            } else {
+                exceptions.add(new InvalidQueryException("Invalid operation: " + node.getOperation()));
+            }
+
+            if (node.getType() == TYPE_LONG) {
+                sb.append(node.getLongValue());
+            } else if (node.getType() == TYPE_DOUBLE) {
+                sb.append(node.getDoubleValue());
+            } else if (node.getType() == TYPE_STRING) {
+                sb.append("'").append(node.getStringValue().replaceAll("'", "''")).append("'");
+            } else if (node.getType() == TYPE_DATE || node.getType() == TYPE_TIMESTAMP) {
+                Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+                cal.setTime(node.getDateValue());
+                sb.append(XPathQueryBuilder.XS_DATETIME.toJCRName(resolver));
+                sb.append("('").append(ISO8601.format(cal)).append("')");
+            } else {
+                exceptions.add(new InvalidQueryException("Invalid type: " + node.getType()));
+            }
+
+            if (node.getOperation() == OPERATION_LIKE) {
+                sb.append(")");
+            }
+        } catch (NoPrefixDeclaredException e) {
+            exceptions.add(e);
+        }
+        return sb;
+    }
+
+    public Object visit(OrderQueryNode node, Object data) {
+        // @todo implement
+        return data;
+    }
+}

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/XPathQueryBuilder.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/XPathQueryBuilder.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/XPathQueryBuilder.java&r1=125777&p2=incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/XPathQueryBuilder.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/XPathQueryBuilder.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/XPathQueryBuilder.java	Thu Jan 20 07:10:22 2005
@@ -25,10 +25,15 @@
 import org.apache.jackrabbit.core.search.OrQueryNode;
 import org.apache.jackrabbit.core.search.RelationQueryNode;
 import org.apache.jackrabbit.core.search.NotQueryNode;
+import org.apache.jackrabbit.core.search.TextsearchQueryNode;
+import org.apache.jackrabbit.core.search.NodeTypeQueryNode;
 import org.apache.jackrabbit.core.NamespaceResolver;
 import org.apache.jackrabbit.core.QName;
 import org.apache.jackrabbit.core.SearchManager;
 import org.apache.jackrabbit.core.NoPrefixDeclaredException;
+import org.apache.jackrabbit.core.IllegalNameException;
+import org.apache.jackrabbit.core.UnknownPrefixException;
+import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 
 import javax.jcr.query.InvalidQueryException;
 import javax.jcr.util.ISO8601;
@@ -43,13 +48,19 @@
 public class XPathQueryBuilder implements XPathVisitor {
 
     /** QName for 'fn:not' */
-    private static final QName FN_NOT = new QName(SearchManager.NS_FN_URI, "not");
+    static final QName FN_NOT = new QName(SearchManager.NS_FN_URI, "not");
 
     /** QName for 'not' as defined in XPath 1.0 (no prefix) */
-    private static final QName FN_NOT_10 = new QName("", "not");
+    static final QName FN_NOT_10 = new QName("", "not");
 
     /** QName for xs:dateTime */
-    private static final QName XS_DATETIME = new QName(SearchManager.NS_XS_URI, "dateTime");
+    static final QName XS_DATETIME = new QName(SearchManager.NS_XS_URI, "dateTime");
+
+    /** QName for jcrfn:like */
+    static final QName JCRFN_LIKE = new QName(SearchManager.NS_JCRFN_URI, "like");
+
+    /** QName for jcrfn:contains */
+    static final QName JCRFN_CONTAINS = new QName(SearchManager.NS_JCRFN_URI, "contains");
 
     /** String constant for operator 'eq' */
     private static final String OP_EQ = "eq";
@@ -140,8 +151,8 @@
         QueryRootNode root = new XPathQueryBuilder(statement, resolver).getRootNode();
         LocationStepQueryNode[] steps = root.getLocationNode().getPathSteps();
         if (steps.length > 0) {
-            String nameTest = steps[0].getNameTest();
-            if (nameTest == null || nameTest.length() > 0) {
+            QName nameTest = steps[0].getNameTest();
+            if (nameTest == null || nameTest.getLocalName().length() > 0) {
                 throw new InvalidQueryException("Path must be absolute: " + statement);
             }
         }
@@ -149,6 +160,19 @@
     }
 
     /**
+     * Creates a String representation of the query node tree in XPath syntax.
+     * @param root the root of the query node tree.
+     * @param resolver to resolve QNames.
+     * @return a String representation of the query node tree.
+     * @throws InvalidQueryException if the query node tree cannot be converted
+     *   into a String representation due to restrictions in XPath.
+     */
+    public static String toString(QueryRootNode root, NamespaceResolver resolver)
+            throws InvalidQueryException {
+        return QueryFormat.toString(root, resolver);
+    }
+
+    /**
      * Returns the root node of the <code>QueryNode</code> tree.
      * @return the root node of the <code>QueryNode</code> tree.
      */
@@ -172,14 +196,13 @@
                 data = createPathQueryNode(node);
                 break;
             case XPathTreeConstants.JJTROOT:
-                ((PathQueryNode) data).addPathStep(new LocationStepQueryNode((QueryNode) data, "", false));
+                ((PathQueryNode) data).addPathStep(new LocationStepQueryNode((QueryNode) data, new QName("", ""), false));
                 break;
             case XPathTreeConstants.JJTROOTDESCENDANTS:
-                ((PathQueryNode) data).addPathStep(new LocationStepQueryNode((QueryNode) data, "", false));
+                ((PathQueryNode) data).addPathStep(new LocationStepQueryNode((QueryNode) data, new QName("", ""), false));
                 break;
             case XPathTreeConstants.JJTSTEPEXPR:
                 if (isAttributeAxis(node)) {
-                    // @todo do what?
                     // traverse
                     node.childrenAccept(this, data);
                 } else {
@@ -192,7 +215,8 @@
                 break;
             case XPathTreeConstants.JJTNAMETEST:
                 if (data instanceof LocationStepQueryNode
-                        || data instanceof RelationQueryNode) {
+                        || data instanceof RelationQueryNode
+                        || data instanceof PathQueryNode) {
                     createNameTest(node, (QueryNode) data);
                 } else {
                     // traverse
@@ -276,10 +300,21 @@
         if (node.jjtGetNumChildren() > 0) {
             SimpleNode child = (SimpleNode) node.jjtGetChild(0);
             if (child.getId() == XPathTreeConstants.JJTQNAME) {
-                if (queryNode instanceof LocationStepQueryNode) {
-                    ((LocationStepQueryNode) queryNode).setNameTest(child.getValue());
-                } else if (queryNode instanceof RelationQueryNode) {
-                    ((RelationQueryNode) queryNode).setProperty(child.getValue());
+                try {
+                    if (queryNode instanceof LocationStepQueryNode) {
+                        QName name = ISO9075.decode(QName.fromJCRName(child.getValue(), resolver));
+                        ((LocationStepQueryNode) queryNode).setNameTest(name);
+                    } else if (queryNode instanceof RelationQueryNode) {
+                        QName name = ISO9075.decode(QName.fromJCRName(child.getValue(), resolver));
+                        ((RelationQueryNode) queryNode).setProperty(name);
+                    } else if (queryNode instanceof PathQueryNode) {
+                        QName name = ISO9075.decode(QName.fromJCRName(child.getValue(), resolver));
+                        root.addSelectProperty(name);
+                    }
+                } catch (IllegalNameException e) {
+                    exceptions.add(new InvalidQueryException("Illegal name: " + child.getValue()));
+                } catch (UnknownPrefixException e) {
+                    exceptions.add(new InvalidQueryException("Unknown prefix: " + child.getValue()));
                 }
             } else if (child.getId() == XPathTreeConstants.JJTSTAR) {
                 if (queryNode instanceof LocationStepQueryNode) {
@@ -324,7 +359,27 @@
 
         // traverse
         node.childrenAccept(this, rqn);
-        queryNode.addOperand(rqn);
+
+        // if property name is jcr:primaryType treat special
+        if (rqn.getProperty().equals(NodeTypeRegistry.JCR_PRIMARY_TYPE)) {
+            if (rqn.getType() == RelationQueryNode.TYPE_STRING) {
+                try {
+                    QName ntName = QName.fromJCRName(rqn.getStringValue(), resolver);
+                    NodeTypeQueryNode ntNode = new NodeTypeQueryNode(queryNode, ntName);
+                    queryNode.addOperand(ntNode);
+                } catch (IllegalNameException e) {
+                    exceptions.add(new InvalidQueryException("Not a valid name: " + rqn.getStringValue()));
+                } catch (UnknownPrefixException e) {
+                    exceptions.add(new InvalidQueryException("Unknown prefix in name: " + rqn.getStringValue()));
+                }
+            } else {
+                // value is not of type string
+                exceptions.add(new InvalidQueryException("Invalid type: jcr:primaryType must be a string"));
+            }
+        } else {
+            // property name is <> jcr:primaryType
+            queryNode.addOperand(rqn);
+        }
     }
 
     /**
@@ -380,6 +435,7 @@
                 if (queryNode instanceof NAryQueryNode) {
                     QueryNode not = new NotQueryNode(queryNode);
                     ((NAryQueryNode) queryNode).addOperand(not);
+                    // @todo is this needed?
                     queryNode = not;
                     // traverse
                     if (node.jjtGetNumChildren() == 2) {
@@ -415,6 +471,57 @@
                 } else {
                     // wrong number of arguments
                     exceptions.add(new InvalidQueryException("Wrong number of arguments for xs:dateTime"));
+                }
+            } else if (JCRFN_CONTAINS.toJCRName(resolver).equals(fName)) {
+                // check number of arguments
+                if (node.jjtGetNumChildren() == 2) {
+                    SimpleNode literal = (SimpleNode) node.jjtGetChild(1).jjtGetChild(0);
+                    if (queryNode instanceof NAryQueryNode) {
+                        if (literal.getId() == XPathTreeConstants.JJTSTRINGLITERAL) {
+                            String value = literal.getValue();
+                            // strip quotes
+                            value = value.substring(1, value.length() - 1);
+                            TextsearchQueryNode contains = new TextsearchQueryNode(queryNode, value);
+                            ((NAryQueryNode) queryNode).addOperand(contains);
+                        } else {
+                            exceptions.add(new InvalidQueryException("Wrong argument type for jcrfn:contains"));
+                        }
+                    } else {
+                        exceptions.add(new InvalidQueryException("Unsupported location for function jcrfn:contains"));
+                    }
+                } else {
+                    // wrong number of arguments
+                    exceptions.add(new InvalidQueryException("Wrong number of arguments for jcrfn:contains"));
+                }
+            } else if (JCRFN_LIKE.toJCRName(resolver).equals(fName)) {
+                // check number of arguments
+                if (node.jjtGetNumChildren() == 3) {
+                    if (queryNode instanceof NAryQueryNode) {
+                        RelationQueryNode like = new RelationQueryNode(queryNode, RelationQueryNode.OPERATION_LIKE);
+                        ((NAryQueryNode) queryNode).addOperand(like);
+
+                        // assign property name
+                        node.jjtGetChild(1).jjtAccept(this, like);
+                        // check property name
+                        if (like.getProperty() == null) {
+                            exceptions.add(new InvalidQueryException("Wrong first argument type for jcrfn:like"));
+                        }
+
+                        SimpleNode literal = (SimpleNode) node.jjtGetChild(2).jjtGetChild(0);
+                        if (literal.getId() == XPathTreeConstants.JJTSTRINGLITERAL) {
+                            String value = literal.getValue();
+                            // strip quotes
+                            value = value.substring(1, value.length() - 1);
+                            like.setStringValue(value);
+                        } else {
+                            exceptions.add(new InvalidQueryException("Wrong second argument type for jcrfn:like"));
+                        }
+                    } else {
+                        exceptions.add(new InvalidQueryException("Unsupported location for function jcrfn:like"));
+                    }
+                } else {
+                    // wrong number of arguments
+                    exceptions.add(new InvalidQueryException("Wrong number of arguments for jcrfn:like"));
                 }
             } else {
                 exceptions.add(new InvalidQueryException("Unsupported function: " + fName));

Modified: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/FulltextQueryTest.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/FulltextQueryTest.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/FulltextQueryTest.java&r1=125777&p2=incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/FulltextQueryTest.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/FulltextQueryTest.java	(original)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/FulltextQueryTest.java	Thu Jan 20 07:10:22 2005
@@ -25,18 +25,6 @@
  */
 public class FulltextQueryTest extends AbstractQueryTest {
 
-    public void testFulltextSimple() throws Exception {
-        Node foo = testRootNode.addNode("foo", NT_UNSTRUCTURED);
-        foo.setProperty("mytext", new String[]{"the quick brown fox jumps over the lazy dog."});
-
-        testRootNode.save();
-
-        String jcrql = "SELECT * FROM * LOCATION " + testRoot + "// TEXTSEARCH \"fox\"";
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        QueryResult result = q.execute();
-        checkResult(result, 1);
-    }
-
     public void testFulltextSimpleSQL1() throws Exception {
         Node foo = testRootNode.addNode("foo", NT_UNSTRUCTURED);
         foo.setProperty("mytext", new String[]{"the quick brown fox jumps over the lazy dog."});
@@ -65,23 +53,6 @@
         checkResult(result, 1);
     }
 
-    public void testFulltextMultiWord() throws Exception {
-        Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
-        n.setProperty("title", new String[]{"test text"});
-        n.setProperty("mytext", new String[]{"the quick brown fox jumps over the lazy dog."});
-
-        n = testRootNode.addNode("node2", NT_UNSTRUCTURED);
-        n.setProperty("title", new String[]{"other text"});
-        n.setProperty("mytext", new String[]{"the quick brown fox jumps over the lazy dog."});
-
-        testRootNode.save();
-
-        String jcrql = "SELECT * FROM * LOCATION " + testRoot + "// TEXTSEARCH \"fox test\"";
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        QueryResult result = q.execute();
-        checkResult(result, 1);
-    }
-
     public void testFulltextMultiWordSQL() throws Exception {
         Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
         n.setProperty("title", new String[]{"test text"});
@@ -101,23 +72,6 @@
         checkResult(result, 1);
     }
 
-    public void testFulltextPhrase() throws Exception {
-        Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
-        n.setProperty("title", new String[]{"test text"});
-        n.setProperty("mytext", new String[]{"the quick brown jumps fox over the lazy dog."});
-
-        n = testRootNode.addNode("node2", NT_UNSTRUCTURED);
-        n.setProperty("title", new String[]{"other text"});
-        n.setProperty("mytext", new String[]{"the quick brown fox jumps over the lazy dog."});
-
-        testRootNode.save();
-
-        String jcrql = "SELECT * FROM * LOCATION " + testRoot + "// TEXTSEARCH \"text 'fox jumps'\"";
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        QueryResult result = q.execute();
-        checkResult(result, 1);
-    }
-
     public void testFulltextPhraseSQL() throws Exception {
         Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
         n.setProperty("title", new String[]{"test text"});
@@ -137,23 +91,6 @@
         checkResult(result, 1);
     }
 
-    public void testFulltextExclude() throws Exception {
-        Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
-        n.setProperty("title", new String[]{"test text"});
-        n.setProperty("mytext", new String[]{"the quick brown fox jumps over the lazy dog."});
-
-        n = testRootNode.addNode("node2", NT_UNSTRUCTURED);
-        n.setProperty("title", new String[]{"other text"});
-        n.setProperty("mytext", new String[]{"the quick brown fox jumps over the lazy dog."});
-
-        superuser.getRootNode().save();
-
-        String jcrql = "SELECT * FROM * LOCATION " + testRoot + "// TEXTSEARCH \"text 'fox jumps' -other\"";
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        QueryResult result = q.execute();
-        checkResult(result, 1);
-    }
-
     public void testFulltextExcludeSQL() throws Exception {
         Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
         n.setProperty("title", new String[]{"test text"});
@@ -173,23 +110,6 @@
         checkResult(result, 1);
     }
 
-    public void testFulltextOr() throws Exception {
-        Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
-        n.setProperty("title", new String[]{"test text"});
-        n.setProperty("mytext", new String[]{"the quick brown fox jumps over the lazy dog."});
-
-        n = testRootNode.addNode("node2", NT_UNSTRUCTURED);
-        n.setProperty("title", new String[]{"other text"});
-        n.setProperty("mytext", new String[]{"the quick brown fox jumps over the lazy dog."});
-
-        testRootNode.save();
-
-        String jcrql = "SELECT * FROM * LOCATION " + testRoot + "// TEXTSEARCH \"'fox jumps' test OR other\"";
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        QueryResult result = q.execute();
-        checkResult(result, 2);
-    }
-
     public void testFulltextOrSQL() throws Exception {
         Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
         n.setProperty("title", new String[]{"test text"});
@@ -205,23 +125,6 @@
                 + "\" WHERE \"jcr:path\" LIKE '" + testRoot + "/%"
                 + "' AND CONTAINS('''fox jumps'' test OR other')";
         Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
-        QueryResult result = q.execute();
-        checkResult(result, 2);
-    }
-
-    public void testFulltextIntercap() throws Exception {
-        Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
-        n.setProperty("title", new String[]{"tEst text"});
-        n.setProperty("mytext", new String[]{"The quick brown Fox jumps over the lazy dog."});
-
-        n = testRootNode.addNode("node2", NT_UNSTRUCTURED);
-        n.setProperty("title", new String[]{"Other text"});
-        n.setProperty("mytext", new String[]{"the quick brown FOX jumPs over the lazy dog."});
-
-        testRootNode.save();
-
-        String jcrql = "SELECT * FROM * LOCATION " + testRoot + "// TEXTSEARCH \"'fox juMps' Test OR otheR\"";
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
         QueryResult result = q.execute();
         checkResult(result, 2);
     }

Modified: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SelectClauseTest.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SelectClauseTest.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SelectClauseTest.java&r1=125777&p2=incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SelectClauseTest.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SelectClauseTest.java	(original)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SelectClauseTest.java	Thu Jan 20 07:10:22 2005
@@ -26,32 +26,6 @@
  */
 public class SelectClauseTest extends AbstractQueryTest {
 
-    public void testSelect() throws RepositoryException {
-        Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
-        n.setProperty("myvalue", new String[]{"foo"});
-        n = testRootNode.addNode("node2", NT_UNSTRUCTURED);
-        n.setProperty("myvalue", new String[]{"bar"});
-        n = testRootNode.addNode("node3", NT_UNSTRUCTURED);
-        n.setProperty("yourvalue", new String[]{"foo"});
-
-        testRootNode.save();
-
-        String jcrql = "SELECT myvalue FROM * LOCATION " + testRoot + "//";
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        QueryResult result = q.execute();
-        checkResult(result, 2);
-
-        jcrql = "SELECT myvalue FROM * LOCATION " + testRoot + "// WHERE yourvalue = \"foo\"";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        result = q.execute();
-        checkResult(result, 0);
-
-        jcrql = "SELECT myvalue FROM *";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        result = q.execute();
-        checkResult(result, 2);
-    }
-
     public void testSelectSQL() throws RepositoryException {
         Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
         n.setProperty("myvalue", new String[]{"foo"});
@@ -81,37 +55,6 @@
         checkResult(result, 2);
     }
 
-    public void testPropertyCount() throws RepositoryException {
-        Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
-        n.setProperty("myvalue", new String[]{"foo"});
-        n = testRootNode.addNode("node2", NT_UNSTRUCTURED);
-        n.setProperty("myvalue", new String[]{"bar"});
-        n = testRootNode.addNode("node3", NT_UNSTRUCTURED);
-        n.setProperty("yourvalue", new String[]{"foo"});
-
-        testRootNode.save();
-
-        String jcrql = "SELECT myvalue FROM * LOCATION " + testRoot + "//";
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        QueryResult result = q.execute();
-        checkResult(result, 2, 2);
-
-        jcrql = "SELECT myvalue FROM * LOCATION " + testRoot + "// WHERE yourvalue = \"foo\"";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        result = q.execute();
-        checkResult(result, 0, 0);
-
-        jcrql = "SELECT myvalue FROM *";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        result = q.execute();
-        checkResult(result, 2, 2);
-
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE myvalue LIKE \"*\"";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        result = q.execute();
-        checkResult(result, 2, 4);
-    }
-
     public void testPropertyCountSQL() throws RepositoryException {
         Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
         n.setProperty("myvalue", new String[]{"foo"});
@@ -146,23 +89,6 @@
         q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         result = q.execute();
         checkResult(result, 2, 4);
-    }
-
-    public void testSameNameSibling() throws RepositoryException {
-        Node n = testRootNode.addNode("node", NT_UNSTRUCTURED);
-        n.setProperty("myvalue", new String[]{"foo"});
-        n = testRootNode.addNode("node", NT_UNSTRUCTURED);
-        n.setProperty("myvalue", new String[]{"bar"});
-        n = testRootNode.addNode("node", NT_UNSTRUCTURED);
-        n.setProperty("yourvalue", new String[]{"foo"});
-
-        testRootNode.save();
-
-        String jcrql = "SELECT myvalue FROM * LOCATION " + testRoot + "/node";
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        QueryResult result = q.execute();
-        checkResult(result, 2, 2);
-
     }
 
     public void testSameNameSiblingSQL() throws RepositoryException {

Modified: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SimpleQueryTest.java
Url: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SimpleQueryTest.java?view=diff&rev=125778&p1=incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SimpleQueryTest.java&r1=125777&p2=incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SimpleQueryTest.java&r2=125778
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SimpleQueryTest.java	(original)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/test/search/SimpleQueryTest.java	Thu Jan 20 07:10:22 2005
@@ -27,46 +27,20 @@
 public class SimpleQueryTest extends AbstractQueryTest {
 
 
-    public void testSimpleQuery1() throws Exception {
-        Node foo = testRootNode.addNode("foo", NT_UNSTRUCTURED);
-        foo.setProperty("bla", new String[]{"bla"});
-
-        testRootNode.save();
-
-        String jcrql = "SELECT * FROM * LOCATION " + testRoot + "/foo WHERE bla=\"bla\"";
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        QueryResult result = q.execute();
-        checkResult(result, 1);
-    }
-
     public void testSimpleQuerySQL1() throws Exception {
         Node foo = testRootNode.addNode("foo", NT_UNSTRUCTURED);
         foo.setProperty("bla", new String[]{"bla"});
 
         testRootNode.save();
 
-        String sql = "SELECT * FROM \"" + NT_BASE
-                + "\" WHERE \"jcr:path\" LIKE '" + testRoot + "/foo'"
+        String sql = "SELECT * FROM nt:base"
+                + " WHERE jcr:path LIKE '" + testRoot + "/foo'"
                 + " AND bla = 'bla'";
         Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         QueryResult result = q.execute();
         checkResult(result, 1);
     }
 
-    public void testSimpleQuery2() throws Exception {
-        Node foo = testRootNode.addNode("foo", NT_UNSTRUCTURED);
-        foo.setProperty("bla", new String[]{"bla"});
-        Node bla = testRootNode.addNode("bla", NT_UNSTRUCTURED);
-        bla.setProperty("bla", new String[]{"bla"});
-
-        testRootNode.save();
-
-        String jcrql = "SELECT * FROM nt:file LOCATION " + testRoot + "// WHERE bla=\"bla\"";
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        QueryResult result = q.execute();
-        checkResult(result, 0);
-    }
-
     public void testSimpleQuerySQL2() throws Exception {
         Node foo = testRootNode.addNode("foo", NT_UNSTRUCTURED);
         foo.setProperty("bla", new String[]{"bla"});
@@ -75,28 +49,14 @@
 
         superuser.getRootNode().save();
 
-        String sql = "SELECT * FROM \"nt:file\"" +
-                " WHERE \"jcr:path\" LIKE '" + testRoot + "/%'"
+        String sql = "SELECT * FROM nt:file" +
+                " WHERE jcr:path LIKE '" + testRoot + "/%'"
                 + " AND bla = 'bla'";
         Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         QueryResult result = q.execute();
         checkResult(result, 0);
     }
 
-    public void testSimpleQuery3() throws Exception {
-        Node foo = testRootNode.addNode("foo", NT_UNSTRUCTURED);
-        foo.setProperty("bla", new String[]{"bla"});
-        Node bla = testRootNode.addNode("bla", NT_UNSTRUCTURED);
-        bla.setProperty("bla", new String[]{"bla"});
-
-        testRootNode.save();
-
-        String jcrql = "SELECT * FROM nt:unstructured LOCATION " + testRoot + "// WHERE bla=\"bla\"";
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        QueryResult result = q.execute();
-        checkResult(result, 2);
-    }
-
     public void testSimpleQuerySQL3() throws Exception {
         Node foo = testRootNode.addNode("foo", NT_UNSTRUCTURED);
         foo.setProperty("bla", new String[]{"bla"});
@@ -105,15 +65,15 @@
 
         testRootNode.save();
 
-        String sql = "SELECT * FROM \"nt:unstructured\"" +
-                " WHERE \"jcr:path\" LIKE '" + testRoot + "/%'"
+        String sql = "SELECT * FROM nt:unstructured" +
+                " WHERE jcr:path LIKE '" + testRoot + "/%'"
                 + " AND bla = 'bla'";
         Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         QueryResult result = q.execute();
         checkResult(result, 2);
     }
 
-    public void testSimpleQuery4() throws Exception {
+    public void testSimpleQuerySQL4() throws Exception {
         Node foo = testRootNode.addNode("foo", NT_UNSTRUCTURED);
         foo.setProperty("bla", new String[]{"bla"});
         Node bla = testRootNode.addNode("bla", NT_UNSTRUCTURED);
@@ -121,8 +81,8 @@
 
         testRootNode.save();
 
-        String jcrql = "SELECT * FROM nt:unstructured LOCATION " + testRoot + "/*";
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        String sql = "SELECT * FROM nt:unstructured WHERE jcr:path LIKE '" + testRoot + "/%'";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         QueryResult result = q.execute();
         checkResult(result, 2);
     }
@@ -140,13 +100,13 @@
 
         testRootNode.save();
 
-        String jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE birth > 1976-01-01T00:00:00.000+01:00";
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        String sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND birth > TIMESTAMP '1976-01-01T00:00:00.000+01:00'";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         QueryResult result = q.execute();
         checkResult(result, 1);
 
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE birth > 1975-01-01T00:00:00.000+01:00";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND birth > TIMESTAMP '1975-01-01T00:00:00.000+01:00'";
+        q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         result = q.execute();
         checkResult(result, 2);
     }
@@ -161,18 +121,18 @@
 
         testRootNode.save();
 
-        String jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value > 0.1e-0";
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        String sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value > 0.1e-0";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         QueryResult result = q.execute();
         checkResult(result, 1);
 
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value > -0.1";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value > -0.1";
+        q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         result = q.execute();
         checkResult(result, 2);
 
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value > -1.5";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value > -1.5";
+        q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         result = q.execute();
         checkResult(result, 3);
     }
@@ -187,18 +147,18 @@
 
         testRootNode.save();
 
-        String jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value > 0";
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        String sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value > 0";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         QueryResult result = q.execute();
         checkResult(result, 1);
 
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value > -1";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value > -1";
+        q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         result = q.execute();
         checkResult(result, 2);
 
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value > -2";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value > -2";
+        q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         result = q.execute();
         checkResult(result, 3);
     }
@@ -213,28 +173,18 @@
 
         testRootNode.save();
 
-        String jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value LIKE \"ping\"";
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        String sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value LIKE 'ping'";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         QueryResult result = q.execute();
         checkResult(result, 1);
 
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value LIKE \"?ing\"";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value LIKE '_ing'";
+        q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         result = q.execute();
         checkResult(result, 2);
 
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value LIKE \"*ing\"";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        result = q.execute();
-        checkResult(result, 3);
-
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value LIKE \"_ing\"";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        result = q.execute();
-        checkResult(result, 2);
-
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value LIKE \"%ing\"";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value LIKE '%ing'";
+        q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         result = q.execute();
         checkResult(result, 3);
     }
@@ -249,28 +199,18 @@
 
         testRootNode.save();
 
-        String jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value LIKE \"ping\"";
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        String sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value LIKE 'ping'";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         QueryResult result = q.execute();
         checkResult(result, 1);
 
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value LIKE \"p?ng\"";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value LIKE 'p_ng'";
+        q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         result = q.execute();
         checkResult(result, 2);
 
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value LIKE \"p*ng\"";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        result = q.execute();
-        checkResult(result, 3);
-
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value LIKE \"p_ng\"";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        result = q.execute();
-        checkResult(result, 2);
-
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value LIKE \"p%ng\"";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value LIKE 'p%ng'";
+        q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         result = q.execute();
         checkResult(result, 3);
     }
@@ -285,64 +225,58 @@
 
         testRootNode.save();
 
-        String jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value LIKE \"bli\"";
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        String sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value LIKE 'bli'";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         QueryResult result = q.execute();
         checkResult(result, 1);
 
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value LIKE \"bl?\"";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        result = q.execute();
-        checkResult(result, 2);
-
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value LIKE \"bl*\"";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
-        result = q.execute();
-        checkResult(result, 3);
-
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value LIKE \"bl_\"";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value LIKE 'bl_'";
+        q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         result = q.execute();
         checkResult(result, 2);
 
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value LIKE \"bl%\"";
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value LIKE 'bl%'";
+        q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         result = q.execute();
         checkResult(result, 3);
     }
 
     public void testLikePatternEscaped() throws Exception {
         Node n = testRootNode.addNode("node1", NT_UNSTRUCTURED);
-        n.setProperty("value", new String[]{"foo\\?bar"});
+        n.setProperty("value", new String[]{"foo\\_bar"});
         n = testRootNode.addNode("node2", NT_UNSTRUCTURED);
         n.setProperty("value", new String[]{"foobar"});
         n = testRootNode.addNode("node3", NT_UNSTRUCTURED);
-        n.setProperty("value", new String[]{"foo?bar"});
+        n.setProperty("value", new String[]{"foo_bar"});
         n = testRootNode.addNode("node4", NT_UNSTRUCTURED);
         n.setProperty("value", new String[]{"foolbar"});
 
         testRootNode.save();
 
-        String jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value LIKE \"foo\\?bar\""; // matches node3
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        String sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value LIKE 'foo\\_bar' ESCAPE '\\'"; // matches node3
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         QueryResult result = q.execute();
         checkResult(result, 1);
 
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value LIKE \"foo?bar\"";    // matches node3 and node4
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value LIKE 'foo_bar'";    // matches node3 and node4
+        q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         result = q.execute();
         checkResult(result, 2);
 
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value LIKE \"foo*bar\"";  // matches all nodes
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value LIKE 'foo%bar'";  // matches all nodes
+        q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         result = q.execute();
         checkResult(result, 4);
 
-        jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value LIKE \"foo\\\\\\?bar\"";  // matches node1
-        q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value LIKE 'foo\\\\\\_bar' ESCAPE '\\'";  // matches node1
+        q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
         result = q.execute();
         checkResult(result, 1);
 
+        sql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value LIKE 'foo\\_bar'";  // matches node1
+        q = superuser.getWorkspace().getQueryManager().createQuery(sql, "sql");
+        result = q.execute();
+        checkResult(result, 1);
     }
 
     public void testNotEqual() throws Exception {
@@ -355,8 +289,8 @@
 
         testRootNode.save();
 
-        String jcrql = "SELECT * FROM * LOCATION " + testRoot + "// WHERE value <> \"bar\"";
-        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, Query.JCRQL);
+        String jcrql = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testRoot + "/%' AND value <> 'bar'";
+        Query q = superuser.getWorkspace().getQueryManager().createQuery(jcrql, "sql");
         QueryResult result = q.execute();
         checkResult(result, 2);