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 2017/07/28 13:15:43 UTC
svn commit: r1803272 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/
oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/
oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/pro...
Author: thomasm
Date: Fri Jul 28 13:15:43 2017
New Revision: 1803272
URL: http://svn.apache.org/viewvc?rev=1803272&view=rev
Log:
OAK-937 Query engine index selection tweaks: shortcut and hint
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexConstants.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndex.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryOptions.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.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
jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexConstants.java?rev=1803272&r1=1803271&r2=1803272&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexConstants.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexConstants.java Fri Jul 28 13:15:43 2017
@@ -103,4 +103,10 @@ public interface IndexConstants {
* The time is in string for as per Type.DATE
*/
String CHECKPOINT_CREATION_TIME = "indexingCheckpointTime";
+
+ /**
+ * The index name hint (when using "option(index abc)", this is "abc")
+ */
+ String INDEX_NAME_OPTION = ":indexName";
+
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndex.java?rev=1803272&r1=1803271&r2=1803272&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndex.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndex.java Fri Jul 28 13:15:43 2017
@@ -18,12 +18,16 @@
*/
package org.apache.jackrabbit.oak.plugins.index.nodetype;
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_NAME_OPTION;
+
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
import org.apache.jackrabbit.oak.spi.query.Cursor;
+import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.plugins.index.Cursors;
import org.apache.jackrabbit.oak.spi.query.Filter;
import org.apache.jackrabbit.oak.spi.query.QueryIndex;
+import org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction;
import org.apache.jackrabbit.oak.spi.state.NodeState;
/**
@@ -63,6 +67,11 @@ class NodeTypeIndex implements QueryInde
// doesn't have a node type restriction
return Double.POSITIVE_INFINITY;
}
+ PropertyRestriction indexName = filter.getPropertyRestriction(INDEX_NAME_OPTION);
+ if (wrongIndexName(indexName)) {
+ return Double.POSITIVE_INFINITY;
+ }
+
NodeTypeIndexLookup lookup = new NodeTypeIndexLookup(root, mountInfoProvider);
if (lookup.isIndexed(filter.getPath(), filter)) {
return lookup.getCost(filter);
@@ -70,6 +79,13 @@ class NodeTypeIndex implements QueryInde
return Double.POSITIVE_INFINITY;
}
}
+
+ private static boolean wrongIndexName(PropertyRestriction indexName) {
+ if (indexName == null || indexName.first == null) {
+ return false;
+ }
+ return !"nodetype".equals(indexName.first.getValue(Type.STRING));
+ }
@Override
public Cursor query(Filter filter, NodeState root) {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java?rev=1803272&r1=1803271&r2=1803272&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/PropertyIndex.java Fri Jul 28 13:15:43 2017
@@ -19,6 +19,7 @@ package org.apache.jackrabbit.oak.plugin
import static com.google.common.base.Preconditions.checkState;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_CONTENT_NODE_NAME;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NAME;
+import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_NAME_OPTION;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.TYPE_PROPERTY_NAME;
import java.io.UnsupportedEncodingException;
@@ -31,6 +32,7 @@ import org.apache.jackrabbit.oak.api.Typ
import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
import org.apache.jackrabbit.oak.spi.query.Cursor;
import org.apache.jackrabbit.oak.spi.query.Filter;
+import org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction;
import org.apache.jackrabbit.oak.spi.query.QueryIndex;
import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -173,7 +175,11 @@ class PropertyIndex implements QueryInde
// TODO support indexes on a path
// currently, only indexes on the root node are supported
NodeState state = root.getChildNode(INDEX_DEFINITIONS_NAME);
+ PropertyRestriction indexName = filter.getPropertyRestriction(INDEX_NAME_OPTION);
for (ChildNodeEntry entry : state.getChildNodeEntries()) {
+ if (wrongIndexName(entry, indexName)) {
+ continue;
+ }
NodeState definition = entry.getNodeState();
if (PROPERTY.equals(definition.getString(TYPE_PROPERTY_NAME))
&& definition.hasChildNode(INDEX_CONTENT_NODE_NAME)) {
@@ -195,6 +201,13 @@ class PropertyIndex implements QueryInde
return bestPlan;
}
+
+ private static boolean wrongIndexName(ChildNodeEntry entry, PropertyRestriction indexName) {
+ if (indexName == null || indexName.first == null) {
+ return false;
+ }
+ return !entry.getName().equals(indexName.first.getValue(Type.STRING));
+ }
//--------------------------------------------------------< QueryIndex >--
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java?rev=1803272&r1=1803271&r2=1803272&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java Fri Jul 28 13:15:43 2017
@@ -1360,4 +1360,8 @@ public class QueryImpl implements Query
return constraint.containsUnfilteredFullTextCondition();
}
+ public QueryOptions getQueryOptions() {
+ return queryOptions;
+ }
+
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryOptions.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryOptions.java?rev=1803272&r1=1803271&r2=1803272&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryOptions.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryOptions.java Fri Jul 28 13:15:43 2017
@@ -19,6 +19,7 @@ package org.apache.jackrabbit.oak.query;
public class QueryOptions {
public Traversal traversal = Traversal.DEFAULT;
+ public String indexName;
public enum Traversal {
// traversing without index is OK for this query, and does not fail or log a warning
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java?rev=1803272&r1=1803271&r2=1803272&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/SQL2Parser.java Fri Jul 28 13:15:43 2017
@@ -168,9 +168,17 @@ public class SQL2Parser {
QueryOptions options = new QueryOptions();
if (readIf("OPTION")) {
read("(");
- if (readIf("TRAVERSAL")) {
- String n = readName().toUpperCase(Locale.ENGLISH);
- options.traversal = Traversal.valueOf(n);
+ while (true) {
+ if (readIf("TRAVERSAL")) {
+ String n = readName().toUpperCase(Locale.ENGLISH);
+ options.traversal = Traversal.valueOf(n);
+ } else if (readIf("INDEX")) {
+ String n = readName();
+ options.indexName = n;
+ } else {
+ break;
+ }
+ readIf(",");
}
read(")");
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java?rev=1803272&r1=1803271&r2=1803272&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ast/SelectorImpl.java Fri Jul 28 13:15:43 2017
@@ -40,12 +40,14 @@ import org.apache.jackrabbit.oak.api.Typ
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.plugins.memory.PropertyBuilder;
import org.apache.jackrabbit.oak.query.QueryImpl;
+import org.apache.jackrabbit.oak.query.QueryOptions;
import org.apache.jackrabbit.oak.spi.query.fulltext.FullTextExpression;
import org.apache.jackrabbit.oak.query.index.FilterImpl;
import org.apache.jackrabbit.oak.query.plan.ExecutionPlan;
import org.apache.jackrabbit.oak.query.plan.SelectorExecutionPlan;
import org.apache.jackrabbit.oak.spi.query.Cursor;
import org.apache.jackrabbit.oak.plugins.index.Cursors;
+import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
import org.apache.jackrabbit.oak.spi.query.IndexRow;
import org.apache.jackrabbit.oak.plugins.memory.PropertyValues;
import org.apache.jackrabbit.oak.spi.query.QueryConstants;
@@ -412,7 +414,11 @@ public class SelectorImpl extends Source
for (ConstraintImpl constraint : selectorConstraints) {
constraint.restrict(f);
}
-
+ QueryOptions options = query.getQueryOptions();
+ if (options != null && options.indexName != null) {
+ f.restrictProperty(IndexConstants.INDEX_NAME_OPTION,
+ Operator.EQUAL, PropertyValues.newString(options.indexName));
+ }
return f;
}
Modified: 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=1803272&r1=1803271&r2=1803272&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/Statement.java Fri Jul 28 13:15:43 2017
@@ -56,7 +56,7 @@ public class Statement {
String xpathQuery;
- QueryOptions queryOptions = new QueryOptions();
+ QueryOptions queryOptions;
public Statement optimize() {
ignoreOrderByScoreDesc();
@@ -226,9 +226,7 @@ public class Statement {
buff.append(orderList.get(i));
}
}
- if (queryOptions.traversal != Traversal.DEFAULT) {
- buff.append(" option(traversal " + queryOptions.traversal +")");
- }
+ appendQueryOptions(buff, queryOptions);
// leave original xpath string as a comment
appendXPathAsComment(buff, xpathQuery);
return buff.toString();
@@ -327,9 +325,7 @@ public class Statement {
buff.append(orderList.get(i));
}
}
- if (queryOptions.traversal != Traversal.DEFAULT) {
- buff.append(" option(traversal " + queryOptions.traversal +")");
- }
+ appendQueryOptions(buff, queryOptions);
// leave original xpath string as a comment
appendXPathAsComment(buff, xpathQuery);
return buff.toString();
@@ -337,6 +333,27 @@ public class Statement {
}
+ private static void appendQueryOptions(StringBuilder buff, QueryOptions queryOptions) {
+ if (queryOptions == null) {
+ return;
+ }
+ buff.append(" option(");
+ int optionCount = 0;
+ if (queryOptions.traversal != Traversal.DEFAULT) {
+ buff.append("traversal " + queryOptions.traversal);
+ optionCount++;
+ }
+ if (queryOptions.indexName != null) {
+ if (optionCount > 0) {
+ buff.append(", ");
+ }
+ buff.append("index [");
+ buff.append(queryOptions.indexName);
+ buff.append("]");
+ }
+ buff.append(")");
+ }
+
private static void appendXPathAsComment(StringBuilder buff, String xpath) {
if (xpath == null) {
return;
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java?rev=1803272&r1=1803271&r2=1803272&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/query/xpath/XPathToSQL2Converter.java Fri Jul 28 13:15:43 2017
@@ -329,12 +329,21 @@ public class XPathToSQL2Converter {
statement.addOrderBy(order);
} while (readIf(","));
}
- QueryOptions options = new QueryOptions();
+ QueryOptions options = null;
if (readIf("option")) {
read("(");
- if (readIf("traversal")) {
- String type = readIdentifier().toUpperCase(Locale.ENGLISH);
- options.traversal = Traversal.valueOf(type);
+ options = new QueryOptions();
+ while (true) {
+ if (readIf("traversal")) {
+ String type = readIdentifier().toUpperCase(Locale.ENGLISH);
+ options.traversal = Traversal.valueOf(type);
+ } else if (readIf("index")) {
+ String n = readIdentifier();
+ options.indexName = n;
+ } else {
+ break;
+ }
+ readIf(",");
}
read(")");
}
@@ -1126,7 +1135,7 @@ public class XPathToSQL2Converter {
// but no longer in the individual statements
// (can not use clear, because it is shared)
stat.orderList = new ArrayList<Order>();
- stat.queryOptions = new QueryOptions();
+ stat.queryOptions = null;
if (result == null) {
result = stat;
} else {
Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java?rev=1803272&r1=1803271&r2=1803272&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexPlanner.java Fri Jul 28 13:15:43 2017
@@ -33,6 +33,7 @@ import org.apache.jackrabbit.JcrConstant
import org.apache.jackrabbit.oak.api.PropertyValue;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
import org.apache.jackrabbit.oak.plugins.index.lucene.IndexDefinition.IndexingRule;
import org.apache.jackrabbit.oak.plugins.index.lucene.util.FacetHelper;
import org.apache.jackrabbit.oak.spi.query.fulltext.FullTextContains;
@@ -123,6 +124,20 @@ class IndexPlanner {
private IndexPlan.Builder getPlanBuilder() {
log.trace("Evaluating plan with index definition {}", definition);
+
+ // skip index if "option(index <name>)" doesn't match
+ PropertyRestriction indexName = filter.getPropertyRestriction(IndexConstants.INDEX_NAME_OPTION);
+ if (indexName != null && indexName.first != null) {
+ String name = indexName.first.getValue(Type.STRING);
+ String thisName = definition.getIndexName();
+ if (thisName != null) {
+ thisName = PathUtils.getName(thisName);
+ if (!thisName.equals(name)) {
+ return null;
+ }
+ }
+ }
+
FullTextExpression ft = filter.getFullTextConstraint();
if (!definition.getVersion().isAtLeast(IndexFormatVersion.V2)){
@@ -358,7 +373,7 @@ class IndexPlanner {
visitTerm(term.getPropertyName());
return true;
}
-
+
private void visitTerm(String propertyName) {
String p = propertyName;
String propertyPath = null;
@@ -603,7 +618,7 @@ class IndexPlanner {
private boolean notSupportedFeature() {
if(filter.getPathRestriction() == Filter.PathRestriction.NO_RESTRICTION
&& filter.matchesAllTypes()
- && filter.getPropertyRestrictions().isEmpty()) {
+ && filter.getPropertyRestrictions().isEmpty()) {
//This mode includes name(), localname() queries
//OrImpl [a/name] = 'Hello' or [b/name] = 'World'
//Relative parent properties where [../foo1] is not null
@@ -612,7 +627,7 @@ class IndexPlanner {
boolean failTestOnMissingFunctionIndex = true;
if (failTestOnMissingFunctionIndex) {
// this means even just function restrictions fail the test
- // (for example "where upper(name) = 'X'",
+ // (for example "where upper(name) = 'X'",
// if a matching function-based index is missing
return false;
}