You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by th...@apache.org on 2013/07/15 11:07:11 UTC
svn commit: r1503146 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/query/ast/
main/java/org/apache/jackrabbit/oak/query/fulltext/
test/java/org/apache/jackrabbit/oak/query/
test/java/org/apache/jackrabbit/oak/query/ast/
Author: thomasm
Date: Mon Jul 15 09:07:10 2013
New Revision: 1503146
URL: http://svn.apache.org/r1503146
Log:
OAK-890 Query: advanced fulltext search conditions
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElement.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextAnd.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextExpression.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextOr.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextParser.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextTerm.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/SQL2ParserTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/ast/FullTextTest.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElement.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElement.java?rev=1503146&r1=1503145&r2=1503146&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElement.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstElement.java Mon Jul 15 09:07:10 2013
@@ -56,6 +56,8 @@ abstract class AstElement {
*/
protected String validateAndNormalizePath(String path) {
// TODO normalize the path (remove superfluous ".." and "." where possible)
+ // possibly using
+ // PropertyValues.getOakPath(name, query.getNamePathMapper());
query.validatePath(path);
return path;
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java?rev=1503146&r1=1503145&r2=1503146&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/AstVisitorBase.java Mon Jul 15 09:07:10 2013
@@ -69,8 +69,8 @@ public abstract class AstVisitorBase imp
*/
@Override
public boolean visit(JoinImpl node) {
- node.getRight().accept(this);
node.getLeft().accept(this);
+ node.getRight().accept(this);
node.getJoinCondition().accept(this);
return true;
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchImpl.java?rev=1503146&r1=1503145&r2=1503146&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/FullTextSearchImpl.java Mon Jul 15 09:07:10 2013
@@ -69,7 +69,6 @@ public class FullTextSearchImpl extends
} else {
this.propertyName = propertyName;
}
-
this.fullTextSearchExpression = fullTextSearchExpression;
}
@@ -95,6 +94,11 @@ public class FullTextSearchImpl extends
if (relativePath != null) {
propertyName = relativePath + "/" + propertyName;
}
+
+ // temporary workaround to support using an index for
+ // "contains(*, 'x') or contains(a, x') or contains(b, 'x')"
+ // propertyName = "*";
+
builder.append(quote(propertyName));
builder.append(", ");
builder.append(getFullTextSearchExpression());
@@ -122,6 +126,9 @@ public class FullTextSearchImpl extends
@Override
public boolean evaluate() {
+ // disable evaluation if a fulltext index is used, as
+ // we don't know what exact options are used in the fulltext index
+ // (stop word, special characters,...)
if (selector.index instanceof FulltextQueryIndex) {
return true;
}
@@ -156,13 +163,9 @@ public class FullTextSearchImpl extends
}
}
}
- // TODO fulltext conditions: need a way to disable evaluation
- // if a fulltext index is used, to avoid filtering too much
- // (we don't know what exact options are used in the fulltext index)
- // (stop word, special characters,...)
PropertyValue v = fullTextSearchExpression.currentValue();
try {
- FullTextExpression expr = FullTextParser.parse(v.getValue(Type.STRING));
+ FullTextExpression expr = FullTextParser.parse(propertyName, v.getValue(Type.STRING));
return expr.evaluate(buff.toString());
} catch (ParseException e) {
throw new IllegalArgumentException("Invalid expression: " + fullTextSearchExpression, e);
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextAnd.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextAnd.java?rev=1503146&r1=1503145&r2=1503146&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextAnd.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextAnd.java Mon Jul 15 09:07:10 2013
@@ -19,13 +19,18 @@
package org.apache.jackrabbit.oak.query.fulltext;
import java.util.ArrayList;
+import java.util.LinkedHashSet;
/**
* A fulltext "and" condition.
*/
public class FullTextAnd extends FullTextExpression {
- public ArrayList<FullTextExpression> list = new ArrayList<FullTextExpression>();
+ public final ArrayList<FullTextExpression> list;
+
+ public FullTextAnd(ArrayList<FullTextExpression> list) {
+ this.list = list;
+ }
@Override
public boolean evaluate(String value) {
@@ -39,7 +44,17 @@ public class FullTextAnd extends FullTex
@Override
public FullTextExpression simplify() {
- return list.size() == 1 ? list.get(0) : this;
+ // remove duplicates
+ LinkedHashSet<FullTextExpression> newList = new LinkedHashSet<FullTextExpression>();
+ for (int i = 0; i < list.size(); i++) {
+ newList.add(list.get(i).simplify());
+ }
+ if (newList.size() == 1) {
+ return newList.iterator().next();
+ }
+ ArrayList<FullTextExpression> l = new ArrayList<FullTextExpression>(newList.size());
+ l.addAll(newList);
+ return new FullTextAnd(l);
}
@Override
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextExpression.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextExpression.java?rev=1503146&r1=1503145&r2=1503146&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextExpression.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextExpression.java Mon Jul 15 09:07:10 2013
@@ -23,10 +23,62 @@ package org.apache.jackrabbit.oak.query.
*/
public abstract class FullTextExpression {
- public static final int PRECEDENCE_OR = 1, PRECEDENCE_AND = 2, PRECEDENCE_TERM = 3;
+ /**
+ * The operator precedence for OR conditions.
+ */
+ public static final int PRECEDENCE_OR = 1;
+
+ /**
+ * The operator precedence for AND conditions.
+ */
+ public static final int PRECEDENCE_AND = 2;
+ /**
+ * The operator precedence for terms.
+ */
+ public static final int PRECEDENCE_TERM = 3;
+
+ /**
+ * Get the operator precedence.
+ *
+ * @return the precedence
+ */
public abstract int getPrecedence();
+
+ /**
+ * Evaluate whether the value matches the condition.
+ *
+ * @param value the value
+ * @return true if it matches
+ */
public abstract boolean evaluate(String value);
+
+ /**
+ * Simplify the expression if possible (removing duplicate conditions).
+ *
+ * @return the simplified expression
+ */
abstract FullTextExpression simplify();
+ /**
+ * Get the string representation of the condition.
+ */
+ @Override
+ public abstract String toString();
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ } else if (!(other instanceof FullTextExpression)) {
+ return false;
+ }
+ return toString().equals(other.toString());
+ }
+
+ @Override
+ public int hashCode() {
+ return toString().hashCode();
+ }
+
}
\ No newline at end of file
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextOr.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextOr.java?rev=1503146&r1=1503145&r2=1503146&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextOr.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextOr.java Mon Jul 15 09:07:10 2013
@@ -19,12 +19,18 @@
package org.apache.jackrabbit.oak.query.fulltext;
import java.util.ArrayList;
+import java.util.LinkedHashSet;
/**
* A fulltext "or" condition.
*/
public class FullTextOr extends FullTextExpression {
- public ArrayList<FullTextExpression> list = new ArrayList<FullTextExpression>();
+
+ public final ArrayList<FullTextExpression> list;
+
+ public FullTextOr(ArrayList<FullTextExpression> list) {
+ this.list = list;
+ }
@Override
public boolean evaluate(String value) {
@@ -38,7 +44,17 @@ public class FullTextOr extends FullText
@Override
public FullTextExpression simplify() {
- return list.size() == 1 ? list.get(0).simplify() : this;
+ // remove duplicates
+ LinkedHashSet<FullTextExpression> newList = new LinkedHashSet<FullTextExpression>();
+ for (int i = 0; i < list.size(); i++) {
+ newList.add(list.get(i).simplify());
+ }
+ if (newList.size() == 1) {
+ return newList.iterator().next();
+ }
+ ArrayList<FullTextExpression> l = new ArrayList<FullTextExpression>(newList.size());
+ l.addAll(newList);
+ return new FullTextOr(l);
}
@Override
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextParser.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextParser.java?rev=1503146&r1=1503145&r2=1503146&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextParser.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextParser.java Mon Jul 15 09:07:10 2013
@@ -19,6 +19,7 @@
package org.apache.jackrabbit.oak.query.fulltext;
import java.text.ParseException;
+import java.util.ArrayList;
/**
@@ -35,39 +36,43 @@ import java.text.ParseException;
*/
public class FullTextParser {
- String text;
- int parseIndex;
+ private String propertyName;
+ private String text;
+ private int parseIndex;
- public static FullTextExpression parse(String text) throws ParseException {
+ public static FullTextExpression parse(String propertyName, String text) throws ParseException {
FullTextParser p = new FullTextParser();
+ p.propertyName = propertyName;
p.text = text;
FullTextExpression e = p.parseOr();
return e;
}
FullTextExpression parseOr() throws ParseException {
- FullTextOr or = new FullTextOr();
- or.list.add(parseAnd());
+ ArrayList<FullTextExpression> list = new ArrayList<FullTextExpression>();
+ list.add(parseAnd());
while (parseIndex < text.length()) {
if (text.substring(parseIndex).startsWith("OR ")) {
parseIndex += 3;
- or.list.add(parseAnd());
+ list.add(parseAnd());
} else {
break;
}
}
+ FullTextOr or = new FullTextOr(list);
return or.simplify();
}
FullTextExpression parseAnd() throws ParseException {
- FullTextAnd and = new FullTextAnd();
- and.list.add(parseTerm());
+ ArrayList<FullTextExpression> list = new ArrayList<FullTextExpression>();
+ list.add(parseTerm());
while (parseIndex < text.length()) {
if (text.substring(parseIndex).startsWith("OR ")) {
break;
}
- and.list.add(parseTerm());
+ list.add(parseTerm());
}
+ FullTextAnd and = new FullTextAnd(list);
return and.simplify();
}
@@ -149,7 +154,7 @@ public class FullTextParser {
throw getSyntaxError("term");
}
String text = buff.toString();
- FullTextTerm term = new FullTextTerm(text, not, escaped, boost);
+ FullTextTerm term = new FullTextTerm(propertyName, text, not, escaped, boost);
return term.simplify();
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextTerm.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextTerm.java?rev=1503146&r1=1503145&r2=1503146&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextTerm.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/fulltext/FullTextTerm.java Mon Jul 15 09:07:10 2013
@@ -23,12 +23,14 @@ package org.apache.jackrabbit.oak.query.
*/
public class FullTextTerm extends FullTextExpression {
private final boolean not;
+ private final String propertyName;
private final String text;
private final String filteredText;
private final String boost;
private final LikePattern like;
- public FullTextTerm(String text, boolean not, boolean escaped, String boost) {
+ public FullTextTerm(String propertyName, String text, boolean not, boolean escaped, String boost) {
+ this.propertyName = propertyName;
this.text = text;
this.not = not;
this.boost = boost;
@@ -71,7 +73,7 @@ public class FullTextTerm extends FullTe
@Override
public boolean evaluate(String value) {
- // for testFulltextIntercapSQL
+ // toLowerCase for testFulltextIntercapSQL
value = value.toLowerCase();
if (like != null) {
return like.matches(value);
@@ -94,6 +96,11 @@ public class FullTextTerm extends FullTe
if (not) {
buff.append('-');
}
+ if (propertyName != null && "*".equals(propertyName)) {
+ // TODO support property name conditions
+ // (currently disabled)
+ buff.append(propertyName).append(':');
+ }
buff.append('\"');
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
@@ -111,6 +118,10 @@ public class FullTextTerm extends FullTe
return buff.toString();
}
+ public String getPropertyName() {
+ return propertyName;
+ }
+
@Override
public int getPrecedence() {
return PRECEDENCE_TERM;
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/SQL2ParserTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/SQL2ParserTest.java?rev=1503146&r1=1503145&r2=1503146&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/SQL2ParserTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/SQL2ParserTest.java Mon Jul 15 09:07:10 2013
@@ -50,11 +50,7 @@ public class SQL2ParserTest {
.convert("/jcr:root/test/*/nt:resource[@jcr:encoding]"));
}
- /**
- * @see <a
- * href="https://issues.apache.org/jira/browse/OAK-OAK-830">OAK-OAK-830:
- * XPathToSQL2Converter fails to wrap or clauses</a>
- */
+ // see OAK-OAK-830: XPathToSQL2Converter fails to wrap or clauses
@Test
public void testUnwrappedOr() throws ParseException {
String q = new XPathToSQL2Converter()
@@ -62,4 +58,5 @@ public class SQL2ParserTest {
String token = "and (b.[type] = 't1' or b.[type] = 't2' or b.[type] = 't3')";
assertTrue(q.contains(token));
}
+
}
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/ast/FullTextTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/ast/FullTextTest.java?rev=1503146&r1=1503145&r2=1503146&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/ast/FullTextTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/ast/FullTextTest.java Mon Jul 15 09:07:10 2013
@@ -113,12 +113,12 @@ public class FullTextTest {
}
private static String convertPattern(String pattern) throws ParseException {
- FullTextExpression e = FullTextParser.parse(pattern);
+ FullTextExpression e = FullTextParser.parse(null, pattern);
return e.toString();
}
private static boolean test(String pattern, String value) throws ParseException {
- FullTextExpression e = FullTextParser.parse(pattern);
+ FullTextExpression e = FullTextParser.parse(null, pattern);
return e.evaluate(value);
}