Author: thomasm
Date: Thu Oct 24 12:50:13 2013
New Revision: 1535363
URL: http://svn.apache.org/r1535363
Log:
OAK-155 Query: limited support for the deprecated JCR 1.0 query language
Query.SQL (refactor to split parsing and SQL-2 generation)
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Order.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Selector.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
- copied, changed from r1535299,
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/XPathToSQL2Converter.java
Removed:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/XPathToSQL2Converter.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/SQL2ParserTest.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java?rev=1535363&r1=1535362&r2=1535363&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryEngineImpl.java
Thu Oct 24 12:50:13 2013
@@ -34,6 +34,7 @@ import org.apache.jackrabbit.oak.api.Que
import org.apache.jackrabbit.oak.api.Result;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.query.index.TraversingIndex;
+import org.apache.jackrabbit.oak.query.xpath.XPathToSQL2Converter;
import org.apache.jackrabbit.oak.spi.query.Filter;
import org.apache.jackrabbit.oak.spi.query.QueryIndex;
import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java?rev=1535363&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Expression.java
Thu Oct 24 12:50:13 2013
@@ -0,0 +1,327 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.oak.query.xpath;
+
+import java.util.ArrayList;
+
+import org.apache.jackrabbit.oak.query.SQL2Parser;
+import org.apache.jackrabbit.util.ISO9075;
+
+/**
+ * An expression.
+ */
+abstract class Expression {
+
+ static final int PRECEDENCE_OR = 1, PRECEDENCE_AND = 2,
+ PRECEDENCE_CONDITION = 3, PRECEDENCE_OPERAND = 4;
+
+ /**
+ * The "and" combination of two conditions.
+ *
+ * @param old the first expression (may be null)
+ * @param add the second expression (may be null)
+ * @return the combined expression (may be null)
+ */
+ public static Expression and(Expression old, Expression add) {
+ if (old == null) {
+ return add;
+ } else if (add == null) {
+ return old;
+ }
+ return new Expression.Condition(old, "and", add,
Expression.PRECEDENCE_AND);
+ }
+
+ /**
+ * Whether this is a condition.
+ *
+ * @return true if it is
+ */
+ boolean isCondition() {
+ return false;
+ }
+
+ /**
+ * Get the operator / operation precedence. The JCR specification uses:
+ * 1=OR, 2=AND, 3=condition, 4=operand
+ *
+ * @return the precedence (as an example, multiplication needs to return
+ * a higher number than addition)
+ */
+ int getPrecedence() {
+ return PRECEDENCE_OPERAND;
+ }
+
+ /**
+ * Get the column alias name of an expression. For a property, this is the
+ * property name (no matter how many selectors the query contains); for
+ * other expressions it matches the toString() method.
+ *
+ * @return the simple column name
+ */
+ String getColumnAliasName() {
+ return toString();
+ }
+
+ /**
+ * Whether the result of this expression is a name. Names are subject to
+ * ISO9075 encoding.
+ *
+ * @return whether this expression is a name.
+ */
+ boolean isName() {
+ return false;
+ }
+
+ /**
+ * A literal expression.
+ */
+ static class Literal extends Expression {
+
+ final String value;
+ final String rawText;
+
+ Literal(String value, String rawText) {
+ this.value = value;
+ this.rawText = rawText;
+ }
+
+ public static Expression newBoolean(boolean value) {
+ return new Literal(String.valueOf(value), String.valueOf(value));
+ }
+
+ static Literal newNumber(String s) {
+ return new Literal(s, s);
+ }
+
+ static Literal newString(String s) {
+ return new Literal(SQL2Parser.escapeStringLiteral(s), s);
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+
+ }
+
+ /**
+ * A condition.
+ */
+ static class Condition extends Expression {
+
+ final Expression left;
+ final String operator;
+ Expression right;
+ final int precedence;
+
+ /**
+ * Create a new condition.
+ *
+ * @param left the left hand side operator, or null
+ * @param operator the operator
+ * @param right the right hand side operator, or null
+ * @param precedence the operator precedence
(Expression.PRECEDENCE_...)
+ */
+ Condition(Expression left, String operator, Expression right, int
precedence) {
+ this.left = left;
+ this.operator = operator;
+ this.right = right;
+ this.precedence = precedence;
+ }
+
+ @Override
+ int getPrecedence() {
+ return precedence;
+ }
+
+ @Override
+ public String toString() {
+ String leftExpr;
+ boolean leftExprIsName;
+ if (left == null) {
+ leftExprIsName = false;
+ leftExpr = "";
+ } else {
+ leftExprIsName = left.isName();
+ leftExpr = left.toString();
+ if (left.getPrecedence() < precedence) {
+ leftExpr = "(" + leftExpr + ")";
+ }
+ }
+ boolean impossible = false;
+ String rightExpr;
+ if (right == null) {
+ rightExpr = "";
+ } else {
+ if (leftExprIsName && !"like".equals(operator)) {
+ // need to de-escape _x0020_ and so on
+ if (!(right instanceof Literal)) {
+ throw new IllegalArgumentException(
+ "Can only compare a name against a string
literal, not " + right);
+ }
+ Literal l = (Literal) right;
+ String raw = l.rawText;
+ String decoded = ISO9075.decode(raw);
+ String encoded = ISO9075.encode(decoded);
+ rightExpr = SQL2Parser.escapeStringLiteral(decoded);
+ if (!encoded.toUpperCase().equals(raw.toUpperCase())) {
+ // nothing can potentially match
+ impossible = true;
+ }
+ } else {
+ rightExpr = right.toString();
+ }
+ if (right.getPrecedence() < precedence) {
+ rightExpr = "(" + right + ")";
+ }
+ }
+ if (impossible) {
+ // a condition that can not possibly be true
+ return "upper(" + leftExpr + ") = 'never matches'";
+ }
+ return (leftExpr + " " + operator + " " + rightExpr).trim();
+ }
+
+ @Override
+ boolean isCondition() {
+ return true;
+ }
+
+ }
+
+ /**
+ * A function call.
+ */
+ static class Function extends Expression {
+
+ final String name;
+ final ArrayList<Expression> params = new ArrayList<Expression>();
+
+ Function(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buff = new StringBuilder(name);
+ buff.append('(');
+ for (int i = 0; i < params.size(); i++) {
+ if (i > 0) {
+ buff.append(", ");
+ }
+ buff.append(params.get(i).toString());
+ }
+ buff.append(')');
+ return buff.toString();
+ }
+
+ @Override
+ boolean isCondition() {
+ return name.equals("contains") || name.equals("not");
+ }
+
+ @Override
+ boolean isName() {
+ if ("upper".equals(name) || "lower".equals(name)) {
+ return params.get(0).isName();
+ }
+ return "name".equals(name);
+ }
+
+ }
+
+ /**
+ * A cast operation.
+ */
+ static class Cast extends Expression {
+
+ final Expression expr;
+ final String type;
+
+ Cast(Expression expr, String type) {
+ this.expr = expr;
+ this.type = type;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buff = new StringBuilder("cast(");
+ buff.append(expr.toString());
+ buff.append(" as ").append(type).append(')');
+ return buff.toString();
+ }
+
+ @Override
+ boolean isCondition() {
+ return false;
+ }
+
+ }
+
+ /**
+ * A selector parameter.
+ */
+ static class SelectorExpr extends Expression {
+
+ private final Selector selector;
+
+ SelectorExpr(Selector selector) {
+ this.selector = selector;
+ }
+
+ @Override
+ public String toString() {
+ return selector.name;
+ }
+
+ }
+
+ /**
+ * A property expression.
+ */
+ static class Property extends Expression {
+
+ final Selector selector;
+ final String name;
+
+ Property(Selector selector, String name) {
+ this.selector = selector;
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buff = new StringBuilder();
+ if (!selector.onlySelector) {
+ buff.append(selector.name).append('.');
+ }
+ if (name.equals("*")) {
+ buff.append('*');
+ } else {
+ buff.append('[').append(name).append(']');
+ }
+ return buff.toString();
+ }
+
+ @Override
+ public String getColumnAliasName() {
+ return name;
+ }
+
+ }
+
+}
\ No newline at end of file
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Order.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Order.java?rev=1535363&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Order.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Order.java
Thu Oct 24 12:50:13 2013
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.oak.query.xpath;
+
+/**
+ * An order by expression.
+ */
+class Order {
+
+ boolean descending;
+ Expression expr;
+
+ @Override
+ public String toString() {
+ return expr + (descending ? " desc" : "");
+ }
+
+}
\ No newline at end of file
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Selector.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Selector.java?rev=1535363&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Selector.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Selector.java
Thu Oct 24 12:50:13 2013
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.oak.query.xpath;
+
+/**
+ * A selector.
+ */
+class Selector {
+
+ /**
+ * The selector name.
+ */
+ String name;
+
+ /**
+ * Whether this is the only selector in the query.
+ */
+ boolean onlySelector;
+
+ /**
+ * The node type, if set, or null.
+ */
+ String nodeType;
+
+ /**
+ * Whether this is a child node of the previous selector or a given path.
+ * Examples:
+ * <ul><li>/jcr:root/*
+ * </li><li>/jcr:root/test/*
+ * </li><li>/jcr:root/element()
+ * </li><li>/jcr:root/element(*)
+ * </li></ul>
+ */
+ boolean isChild;
+
+ /**
+ * Whether this is a parent node of the previous selector or given path.
+ * Examples:
+ * <ul><li>testroot//child/..[@foo1]
+ * </li><li>/jcr:root/test/descendant/..[@test]
+ * </li></ul>
+ */
+ boolean isParent;
+
+ /**
+ * Whether this is a descendant of the previous selector or a given path.
+ * Examples:
+ * <ul><li>/jcr:root//descendant
+ * </li><li>/jcr:root/test//descendant
+ * </li><li>/jcr:root[@x]
+ * </li><li>/jcr:root (just by itself)
+ * </li></ul>
+ */
+ boolean isDescendant;
+
+ /**
+ * The path (only used for the first selector).
+ */
+ String path = "";
+
+ /**
+ * The node name, if set.
+ */
+ String nodeName;
+
+ /**
+ * The condition for this selector.
+ */
+ Expression condition;
+
+ /**
+ * The join condition from the previous selector.
+ */
+ Expression joinCondition;
+
+}
\ No newline at end of file
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java?rev=1535363&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java
Thu Oct 24 12:50:13 2013
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.oak.query.xpath;
+
+import java.util.ArrayList;
+
+import org.apache.jackrabbit.oak.query.QueryImpl;
+import org.apache.jackrabbit.oak.query.xpath.Expression.Property;
+
+/**
+ * An xpath statement.
+ */
+public class Statement {
+
+ private String xpathQuery;
+
+ private boolean explain;
+ private boolean measure;
+
+ /**
+ * The selector to get the columns from (the selector used in the select
+ * column list).
+ */
+ private Selector columnSelector;
+
+ private ArrayList<Expression> columnList = new ArrayList<Expression>();
+
+ /**
+ * All selectors.
+ */
+ private ArrayList<Selector> selectors;
+
+ private ArrayList<Order> orderList = new ArrayList<Order>();
+
+ @Override
+ public String toString() {
+ StringBuilder buff = new StringBuilder();
+
+ // explain | measure ...
+ if (explain) {
+ buff.append("explain ");
+ } else if (measure) {
+ buff.append("measure ");
+ }
+
+ // select ...
+ buff.append("select ");
+ buff.append(new Expression.Property(columnSelector,
QueryImpl.JCR_PATH).toString());
+ if (selectors.size() > 1) {
+ buff.append(" as
").append('[').append(QueryImpl.JCR_PATH).append(']');
+ }
+ buff.append(", ");
+ buff.append(new Expression.Property(columnSelector,
QueryImpl.JCR_SCORE).toString());
+ if (selectors.size() > 1) {
+ buff.append(" as
").append('[').append(QueryImpl.JCR_SCORE).append(']');
+ }
+ if (columnList.isEmpty()) {
+ buff.append(", ");
+ buff.append(new Expression.Property(columnSelector,
"*").toString());
+ } else {
+ for (int i = 0; i < columnList.size(); i++) {
+ buff.append(", ");
+ Expression e = columnList.get(i);
+ String columnName = e.toString();
+ buff.append(columnName);
+ if (selectors.size() > 1) {
+ buff.append(" as
[").append(e.getColumnAliasName()).append("]");
+ }
+ }
+ }
+
+ // from ...
+ buff.append(" from ");
+ for (int i = 0; i < selectors.size(); i++) {
+ Selector s = selectors.get(i);
+ if (i > 0) {
+ buff.append(" inner join ");
+ }
+ String nodeType = s.nodeType;
+ if (nodeType == null) {
+ nodeType = "nt:base";
+ }
+ buff.append('[' + nodeType + ']').append(" as ").append(s.name);
+ if (s.joinCondition != null) {
+ buff.append(" on ").append(s.joinCondition);
+ }
+ }
+
+ // where ...
+ Expression where = null;
+ for (Selector s : selectors) {
+ where = Expression.and(where, s.condition);
+ }
+ if (where != null) {
+ buff.append(" where ").append(where.toString());
+ }
+
+ // order by ...
+ if (!orderList.isEmpty()) {
+ buff.append(" order by ");
+ for (int i = 0; i < orderList.size(); i++) {
+ if (i > 0) {
+ buff.append(", ");
+ }
+ buff.append(orderList.get(i));
+ }
+ }
+
+ // leave original xpath string as a comment
+ buff.append(" /* xpath: ");
+ buff.append(xpathQuery);
+ buff.append(" */");
+ return buff.toString();
+ }
+
+ public void setExplain(boolean explain) {
+ this.explain = explain;
+ }
+
+ public void setMeasure(boolean measure) {
+ this.measure = measure;
+ }
+
+ public void addSelectColumn(Property p) {
+ columnList.add(p);
+ }
+
+ public void setSelectors(ArrayList<Selector> selectors) {
+ this.selectors = selectors;
+ }
+
+ public void addOrderBy(Order order) {
+ this.orderList.add(order);
+ }
+
+ public void setColumnSelector(Selector columnSelector) {
+ this.columnSelector = columnSelector;
+ }
+
+ public void setOriginalQuery(String xpathQuery) {
+ this.xpathQuery = xpathQuery;
+ }
+
+}
Copied:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
(from r1535299,
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/XPathToSQL2Converter.java)
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java?p2=jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java&p1=jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/XPathToSQL2Converter.java&r1=1535299&r2=1535363&rev=1535363&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/XPathToSQL2Converter.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
Thu Oct 24 12:50:13 2013
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.jackrabbit.oak.query;
+package org.apache.jackrabbit.oak.query.xpath;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.util.ISO9075;
@@ -63,14 +63,18 @@ public class XPathToSQL2Converter {
* @throws ParseException if parsing fails
*/
public String convert(String query) throws ParseException {
+
query = query.trim();
- boolean explain = query.startsWith("explain ");
- if (explain) {
+
+ Statement statement = new Statement();
+
+ if (query.startsWith("explain ")) {
query = query.substring("explain".length()).trim();
+ statement.setExplain(true);
}
- boolean measure = query.startsWith("measure");
- if (measure) {
+ if (query.startsWith("measure")) {
query = query.substring("measure".length()).trim();
+ statement.setMeasure(true);
}
if (query.isEmpty()) {
@@ -78,6 +82,8 @@ public class XPathToSQL2Converter {
query = "//jcr:root";
}
+ statement.setOriginalQuery(query);
+
initialize(query);
expected = new ArrayList<String>();
@@ -89,8 +95,6 @@ public class XPathToSQL2Converter {
currentSelector.name = "a";
- ArrayList<Expression> columnList = new ArrayList<Expression>();
-
String pathPattern = "";
boolean startOfQuery = true;
@@ -188,23 +192,23 @@ public class XPathToSQL2Converter {
}
} else if (readIf("@")) {
rewindSelector();
- Property p = readProperty();
- columnList.add(p);
+ Expression.Property p = readProperty();
+ statement.addSelectColumn(p);
} else if (readIf("rep:excerpt")) {
rewindSelector();
readExcerpt();
- Property p = new Property(currentSelector, "rep:excerpt");
- columnList.add(p);
+ Expression.Property p = new
Expression.Property(currentSelector, "rep:excerpt");
+ statement.addSelectColumn(p);
} else if (readIf("(")) {
rewindSelector();
do {
if (readIf("@")) {
- Property p = readProperty();
- columnList.add(p);
+ Expression.Property p = readProperty();
+ statement.addSelectColumn(p);
} else if (readIf("rep:excerpt")) {
readExcerpt();
- Property p = new Property(currentSelector,
"rep:excerpt");
- columnList.add(p);
+ Expression.Property p = new
Expression.Property(currentSelector, "rep:excerpt");
+ statement.addSelectColumn(p);
}
} while (readIf("|"));
read(")");
@@ -241,7 +245,7 @@ public class XPathToSQL2Converter {
}
if (readIf("[")) {
Expression c = parseConstraint();
- currentSelector.condition = add(currentSelector.condition, c);
+ currentSelector.condition =
Expression.and(currentSelector.condition, c);
read("]");
}
startOfQuery = false;
@@ -256,7 +260,6 @@ public class XPathToSQL2Converter {
if (selectors.size() == 1) {
currentSelector.onlySelector = true;
}
- ArrayList<Order> orderList = new ArrayList<Order>();
if (readIf("order")) {
read("by");
do {
@@ -267,88 +270,17 @@ public class XPathToSQL2Converter {
} else {
readIf("ascending");
}
- orderList.add(order);
+ statement.addOrderBy(order);
} while (readIf(","));
}
if (!currentToken.isEmpty()) {
throw getSyntaxError("<end>");
}
- StringBuilder buff = new StringBuilder();
-
- // explain | measure ...
- if (explain) {
- buff.append("explain ");
- } else if (measure) {
- buff.append("measure ");
- }
-
- // select ...
- buff.append("select ");
- buff.append(new Property(currentSelector,
QueryImpl.JCR_PATH).toString());
- if (selectors.size() > 1) {
- buff.append(" as
").append('[').append(QueryImpl.JCR_PATH).append(']');
- }
- buff.append(", ");
- buff.append(new Property(currentSelector,
QueryImpl.JCR_SCORE).toString());
- if (selectors.size() > 1) {
- buff.append(" as
").append('[').append(QueryImpl.JCR_SCORE).append(']');
- }
- if (columnList.isEmpty()) {
- buff.append(", ");
- buff.append(new Property(currentSelector, "*").toString());
- } else {
- for (int i = 0; i < columnList.size(); i++) {
- buff.append(", ");
- Expression e = columnList.get(i);
- String columnName = e.toString();
- buff.append(columnName);
- if (selectors.size() > 1) {
- buff.append(" as
[").append(e.getColumnAliasName()).append("]");
- }
- }
- }
-
- // from ...
- buff.append(" from ");
- for (int i = 0; i < selectors.size(); i++) {
- Selector s = selectors.get(i);
- if (i > 0) {
- buff.append(" inner join ");
- }
- String nodeType = s.nodeType;
- if (nodeType == null) {
- nodeType = "nt:base";
- }
- buff.append('[' + nodeType + ']').append(" as ").append(s.name);
- if (s.joinCondition != null) {
- buff.append(" on ").append(s.joinCondition);
- }
- }
+ statement.setColumnSelector(currentSelector);
+ statement.setSelectors(selectors);
- // where ...
- Expression where = null;
- for (Selector s : selectors) {
- where = add(where, s.condition);
- }
- if (where != null) {
- buff.append(" where ").append(where.toString());
- }
- // order by ...
- if (!orderList.isEmpty()) {
- buff.append(" order by ");
- for (int i = 0; i < orderList.size(); i++) {
- if (i > 0) {
- buff.append(", ");
- }
- buff.append(orderList.get(i));
- }
- }
+ return statement.toString();
- // leave original xpath string as a comment
- buff.append(" /* xpath: ");
- buff.append(query);
- buff.append(" */");
- return buff.toString();
}
private void appendNodeName(String name) {
@@ -391,15 +323,15 @@ public class XPathToSQL2Converter {
Expression condition = currentSelector.condition;
Expression joinCondition = null;
if (currentSelector.nodeName != null) {
- Function f = new Function("name");
- f.params.add(new SelectorExpr(currentSelector));
+ Expression.Function f = new Expression.Function("name");
+ f.params.add(new Expression.SelectorExpr(currentSelector));
String n = currentSelector.nodeName;
// encode again, because it will be decoded again
n = ISO9075.encode(n);
- Condition c = new Condition(f, "=",
- Literal.newString(n),
+ Expression.Condition c = new Expression.Condition(f, "=",
+ Expression.Literal.newString(n),
Expression.PRECEDENCE_CONDITION);
- condition = add(condition, c);
+ condition = Expression.and(condition, c);
}
if (currentSelector.isDescendant) {
if (isFirstSelector) {
@@ -407,24 +339,24 @@ public class XPathToSQL2Converter {
if (!PathUtils.isAbsolute(path)) {
path = PathUtils.concat("/", path);
}
- Function c = new Function("isdescendantnode");
- c.params.add(new SelectorExpr(currentSelector));
- c.params.add(Literal.newString(path));
- condition = add(condition, c);
+ Expression.Function c = new
Expression.Function("isdescendantnode");
+ c.params.add(new Expression.SelectorExpr(currentSelector));
+ c.params.add(Expression.Literal.newString(path));
+ condition = Expression.and(condition, c);
}
} else {
- Function c = new Function("isdescendantnode");
- c.params.add(new SelectorExpr(currentSelector));
- c.params.add(new SelectorExpr(selectors.get(selectors.size() -
1)));
+ Expression.Function c = new
Expression.Function("isdescendantnode");
+ c.params.add(new Expression.SelectorExpr(currentSelector));
+ c.params.add(new
Expression.SelectorExpr(selectors.get(selectors.size() - 1)));
joinCondition = c;
}
} else if (currentSelector.isParent) {
if (isFirstSelector) {
throw getSyntaxError();
} else {
- Function c = new Function("ischildnode");
- c.params.add(new SelectorExpr(selectors.get(selectors.size() -
1)));
- c.params.add(new SelectorExpr(currentSelector));
+ Expression.Function c = new Expression.Function("ischildnode");
+ c.params.add(new
Expression.SelectorExpr(selectors.get(selectors.size() - 1)));
+ c.params.add(new Expression.SelectorExpr(currentSelector));
joinCondition = c;
}
} else if (currentSelector.isChild) {
@@ -433,15 +365,15 @@ public class XPathToSQL2Converter {
if (!PathUtils.isAbsolute(path)) {
path = PathUtils.concat("/", path);
}
- Function c = new Function("ischildnode");
- c.params.add(new SelectorExpr(currentSelector));
- c.params.add(Literal.newString(path));
- condition = add(condition, c);
+ Expression.Function c = new
Expression.Function("ischildnode");
+ c.params.add(new Expression.SelectorExpr(currentSelector));
+ c.params.add(Expression.Literal.newString(path));
+ condition = Expression.and(condition, c);
}
} else {
- Function c = new Function("ischildnode");
- c.params.add(new SelectorExpr(currentSelector));
- c.params.add(new SelectorExpr(selectors.get(selectors.size() -
1)));
+ Expression.Function c = new Expression.Function("ischildnode");
+ c.params.add(new Expression.SelectorExpr(currentSelector));
+ c.params.add(new
Expression.SelectorExpr(selectors.get(selectors.size() - 1)));
joinCondition = c;
}
} else {
@@ -449,10 +381,10 @@ public class XPathToSQL2Converter {
// a child node of a given path, such as "/test"
// use the same selector for now, and extend the path
} else if (PathUtils.isAbsolute(path)) {
- Function c = new Function("issamenode");
- c.params.add(new SelectorExpr(currentSelector));
- c.params.add(Literal.newString(path));
- condition = add(condition, c);
+ Expression.Function c = new Expression.Function("issamenode");
+ c.params.add(new Expression.SelectorExpr(currentSelector));
+ c.params.add(Expression.Literal.newString(path));
+ condition = Expression.and(condition, c);
}
}
if (force || condition != null || joinCondition != null) {
@@ -463,25 +395,16 @@ public class XPathToSQL2Converter {
Selector nextSelector = new Selector();
nextSelector.name = nextSelectorName;
currentSelector.condition = condition;
- currentSelector.joinCondition = add(currentSelector.joinCondition,
joinCondition);
+ currentSelector.joinCondition =
Expression.and(currentSelector.joinCondition, joinCondition);
selectors.add(currentSelector);
currentSelector = nextSelector;
}
}
- private static Expression add(Expression old, Expression add) {
- if (old == null) {
- return add;
- } else if (add == null) {
- return old;
- }
- return new Condition(old, "and", add, Expression.PRECEDENCE_AND);
- }
-
private Expression parseConstraint() throws ParseException {
Expression a = parseAnd();
while (readIf("or")) {
- a = new Condition(a, "or", parseAnd(), Expression.PRECEDENCE_OR);
+ a = new Expression.Condition(a, "or", parseAnd(),
Expression.PRECEDENCE_OR);
}
return a;
}
@@ -489,7 +412,7 @@ public class XPathToSQL2Converter {
private Expression parseAnd() throws ParseException {
Expression a = parseCondition();
while (readIf("and")) {
- a = new Condition(a, "and", parseCondition(),
Expression.PRECEDENCE_AND);
+ a = new Expression.Condition(a, "and", parseCondition(),
Expression.PRECEDENCE_AND);
}
return a;
}
@@ -499,13 +422,13 @@ public class XPathToSQL2Converter {
if (readIf("fn:not") || readIf("not")) {
read("(");
a = parseConstraint();
- if (a instanceof Condition && ((Condition) a).operator.equals("is
not null")) {
+ if (a instanceof Expression.Condition && ((Expression.Condition)
a).operator.equals("is not null")) {
// not(@property) -> @property is null
- Condition c = (Condition) a;
- c = new Condition(c.left, "is null", null,
Expression.PRECEDENCE_CONDITION);
+ Expression.Condition c = (Expression.Condition) a;
+ c = new Expression.Condition(c.left, "is null", null,
Expression.PRECEDENCE_CONDITION);
a = c;
} else {
- Function f = new Function("not");
+ Expression.Function f = new Expression.Function("not");
f.params.add(a);
a = f;
}
@@ -523,27 +446,27 @@ public class XPathToSQL2Converter {
return a;
}
- private Condition parseCondition(Expression left) throws ParseException {
- Condition c;
+ private Expression.Condition parseCondition(Expression left) throws
ParseException {
+ Expression.Condition c;
if (readIf("=")) {
- c = new Condition(left, "=", parseExpression(),
Expression.PRECEDENCE_CONDITION);
+ c = new Expression.Condition(left, "=", parseExpression(),
Expression.PRECEDENCE_CONDITION);
} else if (readIf("<>")) {
- c = new Condition(left, "<>", parseExpression(),
Expression.PRECEDENCE_CONDITION);
+ c = new Expression.Condition(left, "<>", parseExpression(),
Expression.PRECEDENCE_CONDITION);
} else if (readIf("!=")) {
- c = new Condition(left, "<>", parseExpression(),
Expression.PRECEDENCE_CONDITION);
+ c = new Expression.Condition(left, "<>", parseExpression(),
Expression.PRECEDENCE_CONDITION);
} else if (readIf("<")) {
- c = new Condition(left, "<", parseExpression(),
Expression.PRECEDENCE_CONDITION);
+ c = new Expression.Condition(left, "<", parseExpression(),
Expression.PRECEDENCE_CONDITION);
} else if (readIf(">")) {
- c = new Condition(left, ">", parseExpression(),
Expression.PRECEDENCE_CONDITION);
+ c = new Expression.Condition(left, ">", parseExpression(),
Expression.PRECEDENCE_CONDITION);
} else if (readIf("<=")) {
- c = new Condition(left, "<=", parseExpression(),
Expression.PRECEDENCE_CONDITION);
+ c = new Expression.Condition(left, "<=", parseExpression(),
Expression.PRECEDENCE_CONDITION);
} else if (readIf(">=")) {
- c = new Condition(left, ">=", parseExpression(),
Expression.PRECEDENCE_CONDITION);
+ c = new Expression.Condition(left, ">=", parseExpression(),
Expression.PRECEDENCE_CONDITION);
// TODO support "x eq y"? it seems this only matches for single value
properties?
// } else if (readIf("eq")) {
// c = new Condition(left, "==", parseExpression(),
Expression.PRECEDENCE_CONDITION);
} else {
- c = new Condition(left, "is not null", null,
Expression.PRECEDENCE_CONDITION);
+ c = new Expression.Condition(left, "is not null", null,
Expression.PRECEDENCE_CONDITION);
}
return c;
}
@@ -552,22 +475,22 @@ public class XPathToSQL2Converter {
if (readIf("@")) {
return readProperty();
} else if (readIf("true")) {
- return Literal.newBoolean(true);
+ return Expression.Literal.newBoolean(true);
} else if (readIf("false")) {
- return Literal.newBoolean(false);
+ return Expression.Literal.newBoolean(false);
} else if (currentTokenType == VALUE_NUMBER) {
- Literal l = Literal.newNumber(currentToken);
+ Expression.Literal l = Expression.Literal.newNumber(currentToken);
read();
return l;
} else if (currentTokenType == VALUE_STRING) {
- Literal l = Literal.newString(currentToken);
+ Expression.Literal l = Expression.Literal.newString(currentToken);
read();
return l;
} else if (readIf("-")) {
if (currentTokenType != VALUE_NUMBER) {
throw getSyntaxError();
}
- Literal l = Literal.newNumber('-' + currentToken);
+ Expression.Literal l = Expression.Literal.newNumber('-' +
currentToken);
read();
return l;
} else if (readIf("+")) {
@@ -604,7 +527,7 @@ public class XPathToSQL2Converter {
} else {
buff.append(readIdentifier());
}
- return new Property(currentSelector, buff.toString());
+ return new Expression.Property(currentSelector,
buff.toString());
} else {
break;
}
@@ -625,54 +548,54 @@ public class XPathToSQL2Converter {
} else {
buff.append("/*");
}
- return new Property(currentSelector, buff.toString());
+ return new Expression.Property(currentSelector, buff.toString());
}
throw getSyntaxError();
}
private Expression parseFunction(String functionName) throws
ParseException {
if ("jcr:like".equals(functionName)) {
- Condition c = new Condition(parseExpression(),
+ Expression.Condition c = new
Expression.Condition(parseExpression(),
"like", null, Expression.PRECEDENCE_CONDITION);
read(",");
c.right = parseExpression();
read(")");
return c;
} else if ("jcr:contains".equals(functionName)) {
- Function f = new Function("contains");
+ Expression.Function f = new Expression.Function("contains");
f.params.add(parseExpression());
read(",");
f.params.add(parseExpression());
read(")");
return f;
} else if ("jcr:score".equals(functionName)) {
- Function f = new Function("score");
- f.params.add(new SelectorExpr(currentSelector));
+ Expression.Function f = new Expression.Function("score");
+ f.params.add(new Expression.SelectorExpr(currentSelector));
read(")");
return f;
} else if ("xs:dateTime".equals(functionName)) {
Expression expr = parseExpression();
- Cast c = new Cast(expr, "date");
+ Expression.Cast c = new Expression.Cast(expr, "date");
read(")");
return c;
} else if ("fn:lower-case".equals(functionName)) {
- Function f = new Function("lower");
+ Expression.Function f = new Expression.Function("lower");
f.params.add(parseExpression());
read(")");
return f;
} else if ("fn:upper-case".equals(functionName)) {
- Function f = new Function("upper");
+ Expression.Function f = new Expression.Function("upper");
f.params.add(parseExpression());
read(")");
return f;
} else if ("fn:name".equals(functionName)) {
- Function f = new Function("name");
+ Expression.Function f = new Expression.Function("name");
if (!readIf(")")) {
// only name(.) and name() are currently supported
read(".");
read(")");
}
- f.params.add(new SelectorExpr(currentSelector));
+ f.params.add(new Expression.SelectorExpr(currentSelector));
return f;
} else if ("jcr:deref".equals(functionName)) {
// TODO maybe support jcr:deref
@@ -714,11 +637,11 @@ public class XPathToSQL2Converter {
read();
}
- private Property readProperty() throws ParseException {
+ private Expression.Property readProperty() throws ParseException {
if (readIf("*")) {
- return new Property(currentSelector, "*");
+ return new Expression.Property(currentSelector, "*");
}
- return new Property(currentSelector, readIdentifier());
+ return new Expression.Property(currentSelector, readIdentifier());
}
private void readExcerpt() throws ParseException {
@@ -1040,382 +963,5 @@ public class XPathToSQL2Converter {
return new ParseException("Query:\n" + query, index);
}
- /**
- * A selector.
- */
- static class Selector {
-
- /**
- * The selector name.
- */
- String name;
-
- /**
- * Whether this is the only selector in the query.
- */
- boolean onlySelector;
-
- /**
- * The node type, if set, or null.
- */
- String nodeType;
-
- /**
- * Whether this is a child node of the previous selector or a given
path.
- * Examples:
- * <ul><li>/jcr:root/*
- * </li><li>/jcr:root/test/*
- * </li><li>/jcr:root/element()
- * </li><li>/jcr:root/element(*)
- * </li></ul>
- */
- boolean isChild;
-
- /**
- * Whether this is a parent node of the previous selector or given
path.
- * Examples:
- * <ul><li>testroot//child/..[@foo1]
- * </li><li>/jcr:root/test/descendant/..[@test]
- * </li></ul>
- */
- boolean isParent;
-
- /**
- * Whether this is a descendant of the previous selector or a given
path.
- * Examples:
- * <ul><li>/jcr:root//descendant
- * </li><li>/jcr:root/test//descendant
- * </li><li>/jcr:root[@x]
- * </li><li>/jcr:root (just by itself)
- * </li></ul>
- */
- boolean isDescendant;
-
- /**
- * The path (only used for the first selector).
- */
- String path = "";
-
- /**
- * The node name, if set.
- */
- String nodeName;
-
- /**
- * The condition for this selector.
- */
- Expression condition;
-
- /**
- * The join condition from the previous selector.
- */
- Expression joinCondition;
-
- }
-
- /**
- * An expression.
- */
- abstract static class Expression {
-
- static final int PRECEDENCE_OR = 1, PRECEDENCE_AND = 2,
- PRECEDENCE_CONDITION = 3, PRECEDENCE_OPERAND = 4;
-
- /**
- * Whether this is a condition.
- *
- * @return true if it is
- */
- boolean isCondition() {
- return false;
- }
-
- /**
- * Get the operator / operation precedence. The JCR specification uses:
- * 1=OR, 2=AND, 3=condition, 4=operand
- *
- * @return the precedence (as an example, multiplication needs to
return
- * a higher number than addition)
- */
- int getPrecedence() {
- return PRECEDENCE_OPERAND;
- }
-
- /**
- * Get the column alias name of an expression. For a property, this is
the
- * property name (no matter how many selectors the query contains); for
- * other expressions it matches the toString() method.
- *
- * @return the simple column name
- */
- String getColumnAliasName() {
- return toString();
- }
-
- /**
- * Whether the result of this expression is a name. Names are subject
to
- * ISO9075 encoding.
- *
- * @return whether this expression is a name.
- */
- boolean isName() {
- return false;
- }
-
- }
-
- /**
- * A selector parameter.
- */
- static class SelectorExpr extends Expression {
-
- private final Selector selector;
-
- SelectorExpr(Selector selector) {
- this.selector = selector;
- }
-
- @Override
- public String toString() {
- return selector.name;
- }
-
- }
-
- /**
- * A literal expression.
- */
- static class Literal extends Expression {
-
- final String value;
- final String rawText;
-
- Literal(String value, String rawText) {
- this.value = value;
- this.rawText = rawText;
- }
-
- public static Expression newBoolean(boolean value) {
- return new Literal(String.valueOf(value), String.valueOf(value));
- }
-
- static Literal newNumber(String s) {
- return new Literal(s, s);
- }
-
- static Literal newString(String s) {
- return new Literal(SQL2Parser.escapeStringLiteral(s), s);
- }
-
- @Override
- public String toString() {
- return value;
- }
-
- }
-
- /**
- * A property expression.
- */
- static class Property extends Expression {
-
- final Selector selector;
- final String name;
-
- Property(Selector selector, String name) {
- this.selector = selector;
- this.name = name;
- }
-
- @Override
- public String toString() {
- StringBuilder buff = new StringBuilder();
- if (!selector.onlySelector) {
- buff.append(selector.name).append('.');
- }
- if (name.equals("*")) {
- buff.append('*');
- } else {
- buff.append('[').append(name).append(']');
- }
- return buff.toString();
- }
-
- @Override
- public String getColumnAliasName() {
- return name;
- }
-
- }
-
- /**
- * A condition.
- */
- static class Condition extends Expression {
-
- final Expression left;
- final String operator;
- Expression right;
- final int precedence;
-
- /**
- * Create a new condition.
- *
- * @param left the left hand side operator, or null
- * @param operator the operator
- * @param right the right hand side operator, or null
- * @param precedence the operator precedence
(Expression.PRECEDENCE_...)
- */
- Condition(Expression left, String operator, Expression right, int
precedence) {
- this.left = left;
- this.operator = operator;
- this.right = right;
- this.precedence = precedence;
- }
-
- @Override
- int getPrecedence() {
- return precedence;
- }
-
- @Override
- public String toString() {
- String leftExpr;
- boolean leftExprIsName;
- if (left == null) {
- leftExprIsName = false;
- leftExpr = "";
- } else {
- leftExprIsName = left.isName();
- leftExpr = left.toString();
- if (left.getPrecedence() < precedence) {
- leftExpr = "(" + leftExpr + ")";
- }
- }
- boolean impossible = false;
- String rightExpr;
- if (right == null) {
- rightExpr = "";
- } else {
- if (leftExprIsName && !"like".equals(operator)) {
- // need to de-escape _x0020_ and so on
- if (!(right instanceof Literal)) {
- throw new IllegalArgumentException(
- "Can only compare a name against a string
literal, not " + right);
- }
- Literal l = (Literal) right;
- String raw = l.rawText;
- String decoded = ISO9075.decode(raw);
- String encoded = ISO9075.encode(decoded);
- rightExpr = SQL2Parser.escapeStringLiteral(decoded);
- if (!encoded.toUpperCase().equals(raw.toUpperCase())) {
- // nothing can potentially match
- impossible = true;
- }
- } else {
- rightExpr = right.toString();
- }
- if (right.getPrecedence() < precedence) {
- rightExpr = "(" + right + ")";
- }
- }
- if (impossible) {
- // a condition that can not possibly be true
- return "upper(" + leftExpr + ") = 'never matches'";
- }
- return (leftExpr + " " + operator + " " + rightExpr).trim();
- }
-
- @Override
- boolean isCondition() {
- return true;
- }
-
- }
-
- /**
- * A function call.
- */
- static class Function extends Expression {
-
- final String name;
- final ArrayList<Expression> params = new ArrayList<Expression>();
-
- Function(String name) {
- this.name = name;
- }
-
- @Override
- public String toString() {
- StringBuilder buff = new StringBuilder(name);
- buff.append('(');
- for (int i = 0; i < params.size(); i++) {
- if (i > 0) {
- buff.append(", ");
- }
- buff.append(params.get(i).toString());
- }
- buff.append(')');
- return buff.toString();
- }
-
- @Override
- boolean isCondition() {
- return name.equals("contains") || name.equals("not");
- }
-
- @Override
- boolean isName() {
- if ("upper".equals(name) || "lower".equals(name)) {
- return params.get(0).isName();
- }
- return "name".equals(name);
- }
-
- }
-
- /**
- * A cast operation.
- */
- static class Cast extends Expression {
-
- final Expression expr;
- final String type;
-
- Cast(Expression expr, String type) {
- this.expr = expr;
- this.type = type;
- }
-
- @Override
- public String toString() {
- StringBuilder buff = new StringBuilder("cast(");
- buff.append(expr.toString());
- buff.append(" as ").append(type).append(')');
- return buff.toString();
- }
-
- @Override
- boolean isCondition() {
- return false;
- }
-
- }
-
- /**
- * An order by expression.
- */
- static class Order {
-
- boolean descending;
- Expression expr;
-
- @Override
- public String toString() {
- return expr + (descending ? " desc" : "");
- }
-
- }
-
}
Modified:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java?rev=1535363&r1=1535362&r2=1535363&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java
Thu Oct 24 12:50:13 2013
@@ -59,6 +59,7 @@ import org.apache.jackrabbit.oak.kernel.
import org.apache.jackrabbit.oak.plugins.memory.BooleanPropertyState;
import org.apache.jackrabbit.oak.plugins.memory.StringPropertyState;
import org.apache.jackrabbit.oak.plugins.value.Conversions;
+import org.apache.jackrabbit.oak.query.xpath.XPathToSQL2Converter;
import org.junit.Before;
/**
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=1535363&r1=1535362&r2=1535363&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
Thu Oct 24 12:50:13 2013
@@ -23,6 +23,7 @@ import static org.apache.jackrabbit.oak.
import java.text.ParseException;
+import org.apache.jackrabbit.oak.query.xpath.XPathToSQL2Converter;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.junit.Test;