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/04/04 16:30:50 UTC
svn commit: r160047 - in incubator/jackrabbit/trunk/src: grammar/sql/
java/org/apache/jackrabbit/core/search/
java/org/apache/jackrabbit/core/search/lucene/
java/org/apache/jackrabbit/core/search/sql/
java/org/apache/jackrabbit/core/search/xpath/
test/org/apache/jackrabbit/core/search/
Author: mreutegg
Date: Mon Apr 4 07:30:48 2005
New Revision: 160047
URL: http://svn.apache.org/viewcvs?view=rev&rev=160047
Log:
JCR-56: allow case insensitive searches
Modified:
incubator/jackrabbit/trunk/src/grammar/sql/JCRSQL.jjt
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/TextsearchQueryNode.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FieldNames.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/NodeIndexer.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTContainsExpression.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/JCRSQLQueryBuilder.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/QueryFormat.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/QueryFormat.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/XPathQueryBuilder.java
incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/core/search/FulltextQueryTest.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&r1=160046&r2=160047
==============================================================================
--- incubator/jackrabbit/trunk/src/grammar/sql/JCRSQL.jjt (original)
+++ incubator/jackrabbit/trunk/src/grammar/sql/JCRSQL.jjt Mon Apr 4 07:30:48 2005
@@ -428,9 +428,15 @@
void ContainsExpression() :
{
Token t = null;
+ QName name = null;
}
{
- <CONTAINS> <LEFT_PAREN> t = <CHAR_STRING_LITERAL> { jjtThis.setQuery(t.image.substring(1, t.image.length() - 1).replaceAll("''", "'")); } <RIGHT_PAREN>
+ <CONTAINS>
+ <LEFT_PAREN>
+ // currently optional
+ ( ( <ASTERISK> | (name = Identifier() { jjtThis.setPropertyName(name); }) ) "," )?
+ t = <CHAR_STRING_LITERAL> { jjtThis.setQuery(t.image.substring(1, t.image.length() - 1).replaceAll("''", "'")); }
+ <RIGHT_PAREN>
}
void Literal() :
@@ -546,7 +552,7 @@
)
)
{
- return name;
+ return jjtThis.getName();
}
}
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&r1=160046&r2=160047
==============================================================================
--- 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 Mon Apr 4 07:30:48 2005
@@ -16,6 +16,8 @@
*/
package org.apache.jackrabbit.core.search;
+import org.apache.jackrabbit.core.QName;
+
/**
* Implements a query node that defines a textsearch clause.
*/
@@ -27,15 +29,37 @@
private final String query;
/**
+ * Limits the scope of this textsearch clause to properties with this name.
+ * If <code>null</code> the scope of this textsearch clause is the fulltext
+ * index of all properties of a node.
+ */
+ private QName propertyName;
+
+ /**
* Creates a new <code>TextsearchQueryNode</code> with a <code>parent</code>
- * and a textsearch <code>query</code> statement.
+ * and a textsearch <code>query</code> statement. The scope of the query
+ * is the fulltext index of the node, that contains all properties.
*
* @param parent the parent node of this query node.
* @param query the textsearch statement.
*/
public TextsearchQueryNode(QueryNode parent, String query) {
+ this(parent, query, null);
+ }
+
+ /**
+ * Creates a new <code>TextsearchQueryNode</code> with a <code>parent</code>
+ * and a textsearch <code>query</code> statement. The scope of the query
+ * is property with name <code>propertyName</code>.
+ *
+ * @param parent the parent node of this query node.
+ * @param query the textsearch statement.
+ * @param propertyName scope of the fulltext search.
+ */
+ public TextsearchQueryNode(QueryNode parent, String query, QName propertyName) {
super(parent);
this.query = query;
+ this.propertyName = propertyName;
}
/**
@@ -63,4 +87,23 @@
return query;
}
+ /**
+ * Returns a property name if the scope is limited to just a single property
+ * or <code>null</code> if the scope is spawned across all properties of a
+ * node.
+ *
+ * @return property name or <code>null</code>.
+ */
+ public QName getPropertyName() {
+ return propertyName;
+ }
+
+ /**
+ * Sets a new name as the search scope for this fulltext query.
+ *
+ * @param property the name of the property.
+ */
+ public void setPropertyName(QName property) {
+ this.propertyName = property;
+ }
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FieldNames.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FieldNames.java?view=diff&r1=160046&r2=160047
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FieldNames.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/lucene/FieldNames.java Mon Apr 4 07:30:48 2005
@@ -35,6 +35,11 @@
public static final String FULLTEXT = "_:FULLTEXT";
/**
+ * Prefix for all field names that are fulltext indexed by property name.
+ */
+ public static final String FULLTEXT_PREFIX = "FULL:";
+
+ /**
* Name of the field that contains the UUID of the parent node. Terms are
* stored and but not tokenized.
*/
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&r1=160046&r2=160047
==============================================================================
--- 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 Mon Apr 4 07:30:48 2005
@@ -16,7 +16,6 @@
*/
package org.apache.jackrabbit.core.search.lucene;
-import org.apache.jackrabbit.core.Constants;
import org.apache.jackrabbit.core.IllegalNameException;
import org.apache.jackrabbit.core.MalformedPathException;
import org.apache.jackrabbit.core.NoPrefixDeclaredException;
@@ -304,8 +303,19 @@
public Object visit(TextsearchQueryNode node, Object data) {
try {
+ String fieldname;
+ if (node.getPropertyName() == null) {
+ // fulltext on node
+ fieldname = FieldNames.FULLTEXT;
+ } else {
+ StringBuffer tmp = new StringBuffer();
+ tmp.append(nsMappings.getPrefix(node.getPropertyName().getNamespaceURI()));
+ tmp.append(":").append(FieldNames.FULLTEXT_PREFIX);
+ tmp.append(node.getPropertyName().getLocalName());
+ fieldname = tmp.toString();
+ }
org.apache.lucene.queryParser.QueryParser parser
- = new org.apache.lucene.queryParser.QueryParser(FieldNames.FULLTEXT, analyzer);
+ = new org.apache.lucene.queryParser.QueryParser(fieldname, analyzer);
parser.setOperator(org.apache.lucene.queryParser.QueryParser.DEFAULT_OPERATOR_AND);
// replace unescaped ' with " and escaped ' with just '
StringBuffer query = new StringBuffer();
@@ -339,6 +349,8 @@
}
}
return parser.parse(query.toString());
+ } catch (NamespaceException e) {
+ exceptions.add(e);
} catch (ParseException e) {
exceptions.add(e);
}
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&r1=160046&r2=160047
==============================================================================
--- 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 Mon Apr 4 07:30:48 2005
@@ -355,7 +355,7 @@
*/
protected void addStringValue(Document doc, String fieldName, Object internalValue) {
String stringValue = String.valueOf(internalValue);
-
+
// simple String
doc.add(new Field(fieldName,
stringValue,
@@ -365,6 +365,15 @@
// also create fulltext index of this value
doc.add(new Field(FieldNames.FULLTEXT,
stringValue,
+ false,
+ true,
+ true));
+ // create fulltext index on property
+ int idx = fieldName.indexOf(':');
+ fieldName = fieldName.substring(0, idx + 1) +
+ FieldNames.FULLTEXT_PREFIX +
+ fieldName.substring(idx + 1);
+ doc.add(new Field(fieldName, stringValue,
false,
true,
true));
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTContainsExpression.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTContainsExpression.java?view=diff&r1=160046&r2=160047
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTContainsExpression.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/ASTContainsExpression.java Mon Apr 4 07:30:48 2005
@@ -16,9 +16,14 @@
*/
package org.apache.jackrabbit.core.search.sql;
+import org.apache.jackrabbit.core.QName;
+
public class ASTContainsExpression extends SimpleNode {
+
private String query;
+ private QName property;
+
public ASTContainsExpression(int id) {
super(id);
}
@@ -35,6 +40,13 @@
this.query = query;
}
+ public QName getPropertyName() {
+ return property;
+ }
+
+ public void setPropertyName(QName property) {
+ this.property = property;
+ }
/**
* 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&r1=160046&r2=160047
==============================================================================
--- 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 Mon Apr 4 07:30:48 2005
@@ -420,7 +420,7 @@
public Object visit(ASTContainsExpression node, Object data) {
NAryQueryNode parent = (NAryQueryNode) data;
- parent.addOperand(new TextsearchQueryNode(parent, node.getQuery()));
+ parent.addOperand(new TextsearchQueryNode(parent, node.getQuery(), node.getPropertyName()));
return parent;
}
Modified: 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=diff&r1=160046&r2=160047
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/QueryFormat.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/sql/QueryFormat.java Mon Apr 4 07:30:48 2005
@@ -254,7 +254,18 @@
StringBuffer sb = (StringBuffer) data;
// escape quote
String query = node.getQuery().replaceAll("'", "''");
- sb.append("CONTAINS('").append(query).append("')");
+ sb.append("CONTAINS(");
+ if (node.getPropertyName() == null) {
+ sb.append("*");
+ } else {
+ try {
+ appendName(node.getPropertyName(), resolver, sb);
+ } catch (NoPrefixDeclaredException e) {
+ exceptions.add(e);
+ }
+ }
+ sb.append(", '");
+ sb.append(query).append("')");
return sb;
}
Modified: 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=diff&r1=160046&r2=160047
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/QueryFormat.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/search/xpath/QueryFormat.java Mon Apr 4 07:30:48 2005
@@ -211,7 +211,13 @@
StringBuffer sb = (StringBuffer) data;
try {
sb.append(XPathQueryBuilder.JCRFN_CONTAINS.toJCRName(resolver));
- sb.append("('");
+ sb.append("(");
+ if (node.getPropertyName() == null) {
+ sb.append(".");
+ } else {
+ sb.append(ISO9075.encode(node.getPropertyName()).toJCRName(resolver));
+ }
+ sb.append(", '");
sb.append(node.getQuery().replaceAll("'", "''"));
sb.append("')");
} catch (NoPrefixDeclaredException e) {
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&r1=160046&r2=160047
==============================================================================
--- 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 Mon Apr 4 07:30:48 2005
@@ -301,7 +301,8 @@
if (queryNode.getType() == QueryNode.TYPE_RELATION
|| queryNode.getType() == QueryNode.TYPE_DEREF
|| queryNode.getType() == QueryNode.TYPE_ORDER
- || queryNode.getType() == QueryNode.TYPE_PATH) {
+ || queryNode.getType() == QueryNode.TYPE_PATH
+ || queryNode.getType() == QueryNode.TYPE_TEXTSEARCH) {
// traverse
node.childrenAccept(this, queryNode);
} else if (queryNode.getType() == QueryNode.TYPE_NOT) {
@@ -324,7 +325,9 @@
}
} else {
if (queryNode.getType() == QueryNode.TYPE_PATH) {
- queryNode = createLocationStep(node, (PathQueryNode) queryNode);
+ queryNode = createLocationStep(node, (NAryQueryNode) queryNode);
+ } else if (queryNode.getType() == QueryNode.TYPE_TEXTSEARCH) {
+ // ignore
} else {
exceptions.add(new InvalidQueryException("Only attribute axis is allowed in predicate"));
}
@@ -334,6 +337,7 @@
if (queryNode.getType() == QueryNode.TYPE_LOCATION
|| queryNode.getType() == QueryNode.TYPE_DEREF
|| queryNode.getType() == QueryNode.TYPE_RELATION
+ || queryNode.getType() == QueryNode.TYPE_TEXTSEARCH
|| queryNode.getType() == QueryNode.TYPE_PATH) {
createNodeTest(node, queryNode);
} else if (queryNode.getType() == QueryNode.TYPE_ORDER) {
@@ -438,7 +442,7 @@
* @param parent the parent <code>PathQueryNode</code>.
* @return the created <code>LocationStepQueryNode</code>.
*/
- private LocationStepQueryNode createLocationStep(SimpleNode node, PathQueryNode parent) {
+ private LocationStepQueryNode createLocationStep(SimpleNode node, NAryQueryNode parent) {
LocationStepQueryNode queryNode = null;
boolean descenant = false;
Node p = node.jjtGetParent();
@@ -446,7 +450,7 @@
SimpleNode c = (SimpleNode) p.jjtGetChild(i);
if (c == node) {
queryNode = new LocationStepQueryNode(parent, null, descenant);
- parent.addPathStep(queryNode);
+ parent.addOperand(queryNode);
break;
}
descenant = (c.getId() == JJTSLASHSLASH
@@ -461,7 +465,7 @@
/**
* Assigns a QName to one of the follwing QueryNodes:
* {@link RelationQueryNode}, {@link DerefQueryNode}, {@link RelationQueryNode},
- * {@link PathQueryNode}, {@link OrderQueryNode}.
+ * {@link PathQueryNode}, {@link OrderQueryNode}, {@link TextsearchQueryNode}.
*
* @param node the current node in the xpath syntax tree.
* @param queryNode the query node.
@@ -489,6 +493,9 @@
} else if (queryNode.getType() == QueryNode.TYPE_ORDER) {
QName name = ISO9075.decode(QName.fromJCRName(child.getValue(), resolver));
root.getOrderNode().addOrderSpec(name, true);
+ } else if (queryNode.getType() == QueryNode.TYPE_TEXTSEARCH) {
+ QName name = ISO9075.decode(QName.fromJCRName(child.getValue(), resolver));
+ ((TextsearchQueryNode) queryNode).setPropertyName(name);
}
} catch (IllegalNameException e) {
exceptions.add(new InvalidQueryException("Illegal name: " + child.getValue()));
@@ -518,20 +525,27 @@
}
// get operation type
String opType = node.getValue();
- // todo distinguish value vs. general comparison
int type = 0;
if (opType.equals(OP_EQ)) {
type = RelationQueryNode.OPERATION_EQ_VALUE;
} else if (opType.equals(OP_SIGN_EQ)) {
type = RelationQueryNode.OPERATION_EQ_GENERAL;
- } else if (opType.equals(OP_GE) || opType.equals(OP_SIGN_GE)) {
- type = RelationQueryNode.OPERATION_GE_VALUE;
- } else if (opType.equals(OP_GT) || opType.equals(OP_SIGN_GT)) {
+ } else if (opType.equals(OP_GT)) {
type = RelationQueryNode.OPERATION_GT_VALUE;
- } else if (opType.equals(OP_LE) || opType.equals(OP_SIGN_LE)) {
+ } else if (opType.equals(OP_SIGN_GT)) {
+ type = RelationQueryNode.OPERATION_GT_GENERAL;
+ } else if (opType.equals(OP_GE)) {
+ type = RelationQueryNode.OPERATION_GE_VALUE;
+ } else if (opType.equals(OP_SIGN_GE)) {
+ type = RelationQueryNode.OPERATION_GE_GENERAL;
+ } else if (opType.equals(OP_LE)) {
type = RelationQueryNode.OPERATION_LE_VALUE;
- } else if (opType.equals(OP_LT) || opType.equals(OP_SIGN_LT)) {
+ } else if (opType.equals(OP_SIGN_LE)) {
+ type = RelationQueryNode.OPERATION_LE_GENERAL;
+ } else if (opType.equals(OP_LT)) {
type = RelationQueryNode.OPERATION_LT_VALUE;
+ } else if (opType.equals(OP_SIGN_LT)) {
+ type = RelationQueryNode.OPERATION_LT_GENERAL;
} else if (opType.equals(OP_NE)) {
type = RelationQueryNode.OPERATION_NE_VALUE;
} else if (opType.equals(OP_SIGN_NE)) {
@@ -668,7 +682,29 @@
}
} else if (JCRFN_CONTAINS.toJCRName(resolver).equals(fName)) {
// check number of arguments
- if (node.jjtGetNumChildren() == 2) {
+ if (node.jjtGetNumChildren() == 3) {
+ if (queryNode instanceof NAryQueryNode) {
+ SimpleNode literal = (SimpleNode) node.jjtGetChild(2).jjtGetChild(0);
+ if (literal.getId() == JJTSTRINGLITERAL) {
+ String value = literal.getValue();
+ if (value.charAt(0) == '"') {
+ value = value.replaceAll("\"\"", "\"");
+ } else {
+ value = value.replaceAll("''", "'");
+ }
+ // strip quotes
+ value = value.substring(1, value.length() - 1);
+ TextsearchQueryNode contains = new TextsearchQueryNode(queryNode, value);
+ // assign property name
+ SimpleNode path = (SimpleNode) node.jjtGetChild(1);
+ path.jjtAccept(this, contains);
+ ((NAryQueryNode) queryNode).addOperand(contains);
+ } else {
+ exceptions.add(new InvalidQueryException("Wrong argument type for jcrfn:contains"));
+ }
+ }
+ // todo first parameter is currently optional -> remove later
+ } else if (node.jjtGetNumChildren() == 2) {
SimpleNode literal = (SimpleNode) node.jjtGetChild(1).jjtGetChild(0);
if (queryNode instanceof NAryQueryNode) {
if (literal.getId() == JJTSTRINGLITERAL) {
Modified: incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/core/search/FulltextQueryTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/core/search/FulltextQueryTest.java?view=diff&r1=160046&r2=160047
==============================================================================
--- incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/core/search/FulltextQueryTest.java (original)
+++ incubator/jackrabbit/trunk/src/test/org/apache/jackrabbit/core/search/FulltextQueryTest.java Mon Apr 4 07:30:48 2005
@@ -17,6 +17,7 @@
package org.apache.jackrabbit.core.search;
import javax.jcr.Node;
+import javax.jcr.RepositoryException;
import javax.jcr.query.Query;
import javax.jcr.query.QueryResult;
@@ -148,5 +149,74 @@
checkResult(result, 2);
}
+ public void testContainsStarSQL() throws RepositoryException {
+ Node n = testRootNode.addNode("node1");
+ 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");
+ n.setProperty("title", new String[]{"The quick brown Fox jumps over the lazy dog."});
+ n.setProperty("mytext", new String[]{"text text"});
+
+ testRootNode.save();
+
+ String sql = "SELECT * FROM nt:unstructured"
+ + " WHERE jcr:path LIKE '" + testRoot + "/%"
+ + "' AND CONTAINS(*, 'fox jumps')";
+ Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, Query.SQL);
+ checkResult(q.execute(), 2);
+ }
+
+ public void testContainsStarXPath() throws RepositoryException {
+ Node n = testRootNode.addNode("node1");
+ 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");
+ n.setProperty("title", new String[]{"The quick brown Fox jumps over the lazy dog."});
+ n.setProperty("mytext", new String[]{"text text"});
+
+ testRootNode.save();
+
+ String sql = "/jcr:root" + testRoot + "/element(*, nt:unstructured)"
+ + "[jcrfn:contains(., 'quick fox')]";
+ Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, Query.XPATH);
+ checkResult(q.execute(), 2);
+ }
+
+ public void testContainsPropScopeSQL() throws RepositoryException {
+ Node n = testRootNode.addNode("node1");
+ 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");
+ n.setProperty("title", new String[]{"The quick brown Fox jumps over the lazy dog."});
+ n.setProperty("mytext", new String[]{"text text"});
+
+ testRootNode.save();
+
+ String sql = "SELECT * FROM nt:unstructured"
+ + " WHERE jcr:path LIKE '" + testRoot + "/%"
+ + "' AND CONTAINS(title, 'fox jumps')";
+ Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, Query.SQL);
+ checkResult(q.execute(), 1);
+ }
+
+ public void testContainsPropScopeXPath() throws RepositoryException {
+ Node n = testRootNode.addNode("node1");
+ 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");
+ n.setProperty("title", new String[]{"The quick brown Fox jumps over the lazy dog."});
+ n.setProperty("mytext", new String[]{"text text"});
+
+ testRootNode.save();
+
+ String sql = "/jcr:root" + testRoot + "/element(*, nt:unstructured)"
+ + "[jcrfn:contains(@title, 'quick fox')]";
+ Query q = superuser.getWorkspace().getQueryManager().createQuery(sql, Query.XPATH);
+ checkResult(q.execute(), 1);
+ }
}