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 2014/04/01 15:16:15 UTC
svn commit: r1583658 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/spi/query/Cursors.java
test/java/org/apache/jackrabbit/oak/spi/query/
test/java/org/apache/jackrabbit/oak/spi/query/CursorsTest.java
Author: thomasm
Date: Tue Apr 1 13:16:15 2014
New Revision: 1583658
URL: http://svn.apache.org/r1583658
Log:
OAK-1654 Composite index aggregates (helper class)
Added:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/query/
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/query/CursorsTest.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursors.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursors.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursors.java?rev=1583658&r1=1583657&r2=1583658&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursors.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/query/Cursors.java Tue Apr 1 13:16:15 2014
@@ -17,6 +17,7 @@
package org.apache.jackrabbit.oak.spi.query;
import java.util.Deque;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -51,6 +52,10 @@ public class Cursors {
private Cursors() {
}
+
+ public static Cursor newIntersectionCursor(Cursor a, Cursor b, QueryEngineSettings settings) {
+ return new IntersectionCursor(a, b, settings);
+ }
/**
* Creates a {@link Cursor} over paths.
@@ -328,4 +333,85 @@ public class Cursors {
}
}
+
+ /**
+ * A cursor that intersects two cursors.
+ */
+ private static class IntersectionCursor extends AbstractCursor {
+
+ private final HashMap<String, IndexRow> secondSet = new HashMap<String, IndexRow>();
+ private final HashSet<String> seen = new HashSet<String>();
+ private final Cursor first, second;
+ private final QueryEngineSettings settings;
+ private boolean init;
+ private boolean closed;
+ private IndexRow current;
+
+ IntersectionCursor(Cursor first, Cursor second, QueryEngineSettings settings) {
+ this.first = first;
+ this.second = second;
+ this.settings = settings;
+ }
+
+ @Override
+ public IndexRow next() {
+ if (closed) {
+ throw new IllegalStateException("This cursor is closed");
+ }
+ if (!init) {
+ fetchNext();
+ init = true;
+ }
+ IndexRow result = current;
+ fetchNext();
+ return result;
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (!closed && !init) {
+ fetchNext();
+ init = true;
+ }
+ return !closed;
+ }
+
+ private void fetchNext() {
+ while (true) {
+ if (!first.hasNext()) {
+ closed = true;
+ return;
+ }
+ IndexRow c = first.next();
+ String p = c.getPath();
+ if (seen.contains(p)) {
+ continue;
+ }
+ if (secondSet.remove(p) != null) {
+ current = c;
+ markSeen(p);
+ return;
+ }
+ while (second.hasNext()) {
+ IndexRow s = second.next();
+ String p2 = s.getPath();
+ if (p.equals(p2)) {
+ current = c;
+ markSeen(p);
+ return;
+ }
+ secondSet.put(p2, s);
+ FilterIterators.checkMemoryLimit(secondSet.size(), settings.getLimitInMemory());
+ }
+ closed = true;
+ }
+ }
+
+ private void markSeen(String path) {
+ seen.add(path);
+ FilterIterators.checkMemoryLimit(seen.size(), settings.getLimitInMemory());
+ }
+
+ }
+
}
Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/query/CursorsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/query/CursorsTest.java?rev=1583658&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/query/CursorsTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/query/CursorsTest.java Tue Apr 1 13:16:15 2014
@@ -0,0 +1,131 @@
+/*
+ * 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.spi.query;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.apache.jackrabbit.oak.api.PropertyValue;
+import org.apache.jackrabbit.oak.query.QueryEngineSettings;
+import org.junit.Test;
+
+/**
+ * Tests the cursors implementations.
+ */
+public class CursorsTest {
+
+ @Test
+ public void intersectionCursor() {
+ QueryEngineSettings s = new QueryEngineSettings();
+ Cursor a = new SimpleCursor("1:", "/b", "/c", "/e", "/e", "/c");
+ Cursor b = new SimpleCursor("2:", "/a", "/c", "/d", "/b", "/c");
+ Cursor c = Cursors.newIntersectionCursor(a, b, s);
+ assertEquals("1:/b, 1:/c", list(c));
+ assertFalse(c.hasNext());
+ }
+
+ @Test
+ public void intersectionCursorExceptions() {
+ QueryEngineSettings s = new QueryEngineSettings();
+ Cursor a = new SimpleCursor("1:", "/b", "/c", "/e", "/e", "/c");
+ Cursor b = new SimpleCursor("2:", "/a", "/c", "/d", "/b", "/c");
+ Cursor c = Cursors.newIntersectionCursor(a, b, s);
+ c.next();
+ c.next();
+ try {
+ c.remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ c.next();
+ fail();
+ } catch (IllegalStateException e) {
+ // expected
+ }
+ }
+
+ static String list(Cursor c) {
+ StringBuilder buff = new StringBuilder();
+ while (c.hasNext()) {
+ buff.append(buff.length() == 0 ? "" : ", ");
+ buff.append(c.next());
+ }
+ return buff.toString();
+ }
+
+ static class SimpleCursor implements Cursor {
+
+ final Iterator<IndexRow> rows;
+
+ SimpleCursor(String idPrefix, String... paths) {
+ ArrayList<IndexRow> list = new ArrayList<IndexRow>();
+ for (String p : paths) {
+ list.add(new SimpleIndexRow(p, idPrefix + p));
+ }
+ rows = list.iterator();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return rows.hasNext();
+ }
+
+ @Override
+ public void remove() {
+ rows.remove();
+ }
+
+ @Override
+ public IndexRow next() {
+ return rows.next();
+ }
+
+ }
+
+ static class SimpleIndexRow implements IndexRow {
+
+ final String path;
+ final String id;
+
+ SimpleIndexRow(String path, String id) {
+ this.path = path;
+ this.id = id;
+ }
+
+ @Override
+ public String getPath() {
+ return path;
+ }
+
+ @Override
+ public PropertyValue getValue(String columnName) {
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return id;
+ }
+
+ }
+}