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 ca...@apache.org on 2018/11/23 12:22:47 UTC
svn commit: r1847255 - in /jackrabbit/oak/branches/1.6: ./
oak-core/src/main/java/org/apache/jackrabbit/oak/query/
oak-core/src/main/java/org/apache/jackrabbit/oak/query/facet/
oak-core/src/test/java/org/apache/jackrabbit/oak/query/
oak-core/src/test/j...
Author: catholicon
Date: Fri Nov 23 12:22:47 2018
New Revision: 1847255
URL: http://svn.apache.org/viewvc?rev=1847255&view=rev
Log:
OAK-7898: Facet queries with UNION should do trivial merge of facets from sub-queries (backport r1846617 from trunk)
Added:
jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/query/ResultRowImplTest.java (with props)
Modified:
jackrabbit/oak/branches/1.6/ (props changed)
jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultRowImpl.java
jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java
jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/query/facet/FacetResult.java
jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/query/facet/package-info.java
jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/query/facet/FacetResultTest.java
jackrabbit/oak/branches/1.6/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/FacetTest.java
Propchange: jackrabbit/oak/branches/1.6/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Nov 23 12:22:47 2018
@@ -1,4 +1,4 @@
/jackrabbit/oak/branches/1.0:1665962
/jackrabbit/oak/branches/1.8:1844835
-/jackrabbit/oak/trunk:1781068,1781075,1781248,1781386,1781846,1781907,1782000,1782029,1782196,1782447,1782476,1782770,1782945,1782966,1782973,1782990,1783061,1783066,1783089,1783104-1783105,1783110,1783619,1783720,1783731,1783733,1783738,1783742,1783773,1783855,1783891,1784023,1784034,1784130,1784162,1784251,1784401,1784551,1784574,1784689,1785095,1785108,1785161,1785172,1785283,1785652,1785838,1785916-1785917,1785919,1785946,1786122,1787074,1787145,1787151,1787217,1787425,1788056,1788378,1788387-1788389,1788463,1788476,1788850,1789056,1789534,1789925,1789940,1789987,1790006,1790013,1790069,1790077,1790079,1790382,1790502-1790503,1792049,1792463,1792742,1792746,1793013,1793088,1793618,1793627,1793644,1794393,1794417,1794683,1795138,1795314,1795330,1795475,1795488,1795491,1795502,1795594,1795613,1795618,1796144,1796230,1796239,1796274,1796278,1796988,1797378,1798035,1798832,1798834,1799219,1799389,1799393,1799924,1800244,1800269,1800606,1800613,1800974,1801011,1801013,1801118-1801119
,1801675,1802260,1802262,1802286,1802548,1802905,1802934,1802938,1802973,1803026,1803247-1803249,1803951,1803953-1803955,1804437,1805851-1805852,1806668,1807308,1807688,1808022,1808053,1808125,1808128,1808142,1808240,1808246,1808731,1809024,1809026,1809131,1809163,1809178-1809179,1809253,1809255-1809256,1809289,1809745,1811071-1811072,1811155,1811380,1811655,1811952,1811963,1811986,1813192,1813538,1814189,1814332,1814397,1814475,1815201,1815438,1815926,1817326,1817919,1817987-1817988,1817990,1818038,1818042,1818056,1818124,1818137,1818554,1818576,1818645,1819048,1819050,1821237,1821325,1821358,1821495,1821516,1821847,1822207,1822850,1823172,1823655,1824896,1825471,1825654,1826237,1826338,1826532,1826640,1826932,1826957,1827472,1827486,1827977,1828502,1829527,1829569,1829587,1829665,1829854,1829864,1829987,1829998,1830019,1830160,1830239,1830748,1831190,1831374,1832258,1832379,1832535,1833308,1834112,1834648-1834649,1834681,1835060,1836082,1837475,1837998,1838637,1839746,1840024,1840
226,1842677,1843175,1843222,1843231,1844549,1844642,1844728,1845730-1845731,1845863,1845865,1846057
+/jackrabbit/oak/trunk:1781068,1781075,1781248,1781386,1781846,1781907,1782000,1782029,1782196,1782447,1782476,1782770,1782945,1782966,1782973,1782990,1783061,1783066,1783089,1783104-1783105,1783110,1783619,1783720,1783731,1783733,1783738,1783742,1783773,1783855,1783891,1784023,1784034,1784130,1784162,1784251,1784401,1784551,1784574,1784689,1785095,1785108,1785161,1785172,1785283,1785652,1785838,1785916-1785917,1785919,1785946,1786122,1787074,1787145,1787151,1787217,1787425,1788056,1788378,1788387-1788389,1788463,1788476,1788850,1789056,1789534,1789925,1789940,1789987,1790006,1790013,1790069,1790077,1790079,1790382,1790502-1790503,1792049,1792463,1792742,1792746,1793013,1793088,1793618,1793627,1793644,1794393,1794417,1794683,1795138,1795314,1795330,1795475,1795488,1795491,1795502,1795594,1795613,1795618,1796144,1796230,1796239,1796274,1796278,1796988,1797378,1798035,1798832,1798834,1799219,1799389,1799393,1799924,1800244,1800269,1800606,1800613,1800974,1801011,1801013,1801118-1801119
,1801675,1802260,1802262,1802286,1802548,1802905,1802934,1802938,1802973,1803026,1803247-1803249,1803951,1803953-1803955,1804437,1805851-1805852,1806668,1807308,1807688,1808022,1808053,1808125,1808128,1808142,1808240,1808246,1808731,1809024,1809026,1809131,1809163,1809178-1809179,1809253,1809255-1809256,1809289,1809745,1811071-1811072,1811155,1811380,1811655,1811952,1811963,1811986,1813192,1813538,1814189,1814332,1814397,1814475,1815201,1815438,1815926,1817326,1817919,1817987-1817988,1817990,1818038,1818042,1818056,1818124,1818137,1818554,1818576,1818645,1819048,1819050,1821237,1821325,1821358,1821495,1821516,1821847,1822207,1822850,1823172,1823655,1824896,1825471,1825654,1826237,1826338,1826532,1826640,1826932,1826957,1827472,1827486,1827977,1828502,1829527,1829569,1829587,1829665,1829854,1829864,1829987,1829998,1830019,1830160,1830239,1830748,1831190,1831374,1832258,1832379,1832535,1833308,1834112,1834648-1834649,1834681,1835060,1836082,1837475,1837998,1838637,1839746,1840024,1840
226,1842677,1843175,1843222,1843231,1844549,1844642,1844728,1845730-1845731,1845863,1845865,1846057,1846617
/jackrabbit/trunk:1345480
Modified: jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultRowImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultRowImpl.java?rev=1847255&r1=1847254&r2=1847255&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultRowImpl.java (original)
+++ jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/query/ResultRowImpl.java Fri Nov 23 12:22:47 2018
@@ -18,6 +18,7 @@ package org.apache.jackrabbit.oak.query;
import java.util.Arrays;
import java.util.Comparator;
+import java.util.Map;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.api.PropertyValue;
@@ -264,4 +265,16 @@ public class ResultRowImpl implements Re
}
+ static ResultRowImpl getMappingResultRow(ResultRowImpl delegate, final Map<String, String> columnToFacetMap) {
+ if (columnToFacetMap.size() == 0) {
+ return delegate;
+ }
+
+ PropertyValue[] mappedVals = delegate.getValues();
+ for (Map.Entry<String, String> entry : columnToFacetMap.entrySet()) {
+ mappedVals[delegate.query.getColumnIndex(entry.getKey())] = PropertyValues.newString(entry.getValue());
+ }
+ return new ResultRowImpl(delegate.query, delegate.trees, mappedVals,
+ delegate.distinctValues, delegate.orderValues);
+ }
}
\ No newline at end of file
Modified: jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java?rev=1847255&r1=1847254&r2=1847255&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java (original)
+++ jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/query/UnionQueryImpl.java Fri Nov 23 12:22:47 2018
@@ -21,21 +21,22 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import com.google.common.collect.AbstractIterator;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterators;
import com.google.common.collect.Maps;
-
-import org.apache.jackrabbit.oak.api.PropertyValue;
-import org.apache.jackrabbit.oak.api.Result;
+import com.google.common.collect.PeekingIterator;
+import org.apache.jackrabbit.oak.api.*;
import org.apache.jackrabbit.oak.api.Result.SizePrecision;
-import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.query.ast.ColumnImpl;
import org.apache.jackrabbit.oak.query.ast.OrderingImpl;
import org.apache.jackrabbit.oak.query.QueryImpl.MeasuringIterator;
+import org.apache.jackrabbit.oak.query.facet.FacetResult;
import org.apache.jackrabbit.oak.spi.query.PropertyValues;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.collect.Iterators;
+import static org.apache.jackrabbit.oak.query.QueryImpl.REP_FACET;
/**
* Represents a union query.
@@ -295,9 +296,11 @@ public class UnionQueryImpl implements Q
boolean distinct = !unionAll;
Comparator<ResultRowImpl> orderBy = ResultRowImpl.getComparator(orderings);
+ FacetMerger facetMerger = new FacetMerger(left, right);
+
Iterator<ResultRowImpl> it;
- final Iterator<ResultRowImpl> leftRows = left.getRows();
- final Iterator<ResultRowImpl> rightRows = right.getRows();
+ final Iterator<ResultRowImpl> leftRows = facetMerger.getLeftIterator();;
+ final Iterator<ResultRowImpl> rightRows = facetMerger.getRightIterator();
Iterator<ResultRowImpl> leftIter = leftRows;
Iterator<ResultRowImpl> rightIter = rightRows;
@@ -408,4 +411,96 @@ public class UnionQueryImpl implements Q
right.verifyNotPotentiallySlow();
}
+ static class FacetMerger {
+
+ private final Iterator<ResultRowImpl> leftIterator;
+ private final Iterator<ResultRowImpl> rightIterator;
+
+ FacetMerger(Query left, Query right) {
+ ColumnImpl[] columns = left.getColumns();
+ String[] columnNames = new String[columns.length];
+ for (int i = 0; i < columns.length; i++) {
+ columnNames[i] = columns[i].getColumnName();
+ }
+
+ Iterator<ResultRowImpl> lIter = left.getRows();
+ Iterator<ResultRowImpl> rIter = right.getRows();
+
+ if (!hasFacets(columnNames) || !bothHaveRows(lIter, rIter)) {
+ this.leftIterator = lIter;
+ this.rightIterator = rIter;
+
+ return;
+ }
+
+ PeekingIterator<ResultRowImpl> lPeekIter = Iterators.peekingIterator(lIter);
+ PeekingIterator<ResultRowImpl> rPeekIter = Iterators.peekingIterator(rIter);
+
+ final ResultRow lRow = lPeekIter.peek();
+ final ResultRow rRow = rPeekIter.peek();
+
+ FacetResult.FacetResultRow leftResultRow = new FacetResult.FacetResultRow() {
+ @Override
+ public String getValue(String columnName) {
+ PropertyValue value = lRow.getValue(columnName);
+ return value == null ? null : value.getValue(Type.STRING);
+ }
+ };
+ FacetResult.FacetResultRow rightResultRow = new FacetResult.FacetResultRow() {
+ @Override
+ public String getValue(String columnName) {
+ PropertyValue value = rRow.getValue(columnName);
+ return value == null ? null : value.getValue(Type.STRING);
+ }
+ };
+ FacetResult facetResult = new FacetResult(columnNames, leftResultRow, rightResultRow);
+
+ Map<String, String> columnToFacetMap = facetResult.asColumnToFacetJsonMap();
+
+ this.leftIterator = new MappingRowIterator(columnToFacetMap, lPeekIter);
+ this.rightIterator = new MappingRowIterator(columnToFacetMap, rPeekIter);
+ }
+
+ Iterator<ResultRowImpl> getLeftIterator() {
+ return leftIterator;
+ }
+
+ Iterator<ResultRowImpl> getRightIterator() {
+ return rightIterator;
+ }
+
+ private boolean hasFacets(String[] columnNames) {
+ for (String c : columnNames) {
+ if (c.startsWith(REP_FACET + "(")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean bothHaveRows(Iterator<ResultRowImpl> lIter, Iterator<ResultRowImpl> rIter) {
+ return lIter.hasNext() && rIter.hasNext();
+ }
+ }
+
+ static class MappingRowIterator extends AbstractIterator<ResultRowImpl> {
+
+ private final Map<String, String> columnToFacetMap;
+ private final Iterator<ResultRowImpl> delegate;
+
+ MappingRowIterator(Map<String, String> columnToFacetMap, Iterator<ResultRowImpl> delegate) {
+ super();
+ this.columnToFacetMap = columnToFacetMap;
+ this.delegate = delegate;
+ }
+
+ @Override
+ protected ResultRowImpl computeNext() {
+ if (delegate.hasNext()) {
+ return ResultRowImpl.getMappingResultRow(delegate.next(), columnToFacetMap);
+ } else {
+ return endOfData();
+ }
+ }
+ }
}
Modified: jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/query/facet/FacetResult.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/query/facet/FacetResult.java?rev=1847255&r1=1847254&r2=1847255&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/query/facet/FacetResult.java (original)
+++ jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/query/facet/FacetResult.java Fri Nov 23 12:22:47 2018
@@ -25,15 +25,19 @@ import javax.jcr.Value;
import javax.jcr.query.QueryResult;
import javax.jcr.query.Row;
import javax.jcr.query.RowIterator;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import org.apache.jackrabbit.oak.commons.json.JsopBuilder;
import org.apache.jackrabbit.oak.commons.json.JsopReader;
import org.apache.jackrabbit.oak.commons.json.JsopTokenizer;
import org.apache.jackrabbit.oak.query.QueryImpl;
+import org.apache.jackrabbit.oak.spi.query.QueryConstants;
+
+import static java.util.Collections.reverseOrder;
+import static java.util.Comparator.comparingInt;
+import static org.apache.jackrabbit.oak.query.QueryImpl.REP_FACET;
/**
* A facet result is a wrapper for {@link javax.jcr.query.QueryResult} capable of returning information about facets
@@ -47,26 +51,73 @@ public class FacetResult {
try {
RowIterator rows = queryResult.getRows();
if (rows.hasNext()) {
- Row row = rows.nextRow();
- for (String column : queryResult.getColumnNames()) {
- if (column.startsWith(QueryImpl.REP_FACET)) {
- String dimension = column.substring(QueryImpl.REP_FACET.length() + 1, column.length() - 1);
- Value value = row.getValue(column);
- if (value != null) {
- String jsonFacetString = value.getString();
- parseJson(dimension, jsonFacetString);
- }
+ final Row row = rows.nextRow();
+ parseJson(queryResult.getColumnNames(), new FacetResultRow() {
+ @Override
+ public String getValue(String columnName) throws Exception {
+ Value value = row.getValue(columnName);
+ return value == null ? null : value.getString();
}
- }
+ });
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
+ public FacetResult(String[] columnNames, FacetResultRow...rows) {
+ try {
+ for (FacetResultRow row : rows) {
+ parseJson(columnNames, row);
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public Map<String, String> asColumnToFacetJsonMap() {
+ Map<String, String> json = Maps.newHashMap();
+ for (Map.Entry<String, List<Facet>> entry : perDimFacets.entrySet()) {
+ JsopBuilder builder = new JsopBuilder();
+ builder.object();
+
+ for (Facet f : entry.getValue()) {
+ builder.key(f.getLabel());
+ builder.value(f.getCount());
+ }
+
+ builder.endObject();
+
+ json.put(REP_FACET + "(" + entry.getKey() + ")", builder.toString());
+ }
+
+ return json;
+ }
+
+ private void parseJson(String[] columnNames, FacetResultRow row) throws Exception {
+ for (String column : columnNames) {
+ if (column.startsWith(REP_FACET)) {
+ String dimension = column.substring(REP_FACET.length() + 1, column.length() - 1);
+ String value = row.getValue(column);
+ if (value != null) {
+ String jsonFacetString = value;
+ parseJson(dimension, jsonFacetString);
+ }
+ }
+ }
+ }
+
private void parseJson(String dimension, String jsonFacetString) {
JsopTokenizer jsopTokenizer = new JsopTokenizer(jsonFacetString);
- List<Facet> facets = new LinkedList<Facet>();
+ List<Facet> facets = perDimFacets.get(dimension);
+ Map<String, Facet> facetsMap = Maps.newLinkedHashMap();
+ if (facets != null) {
+ for (Facet facet : facets) {
+ if (!facetsMap.containsKey(facet.getLabel())) {
+ facetsMap.put(facet.getLabel(), facet);
+ }
+ }
+ }
int c;
String label = null;
int count;
@@ -76,11 +127,30 @@ public class FacetResult {
} else if (JsopReader.NUMBER == c) {
count = Integer.parseInt(jsopTokenizer.getEscapedToken());
if (label != null) {
- facets.add(new Facet(label, count));
+ if (facetsMap.containsKey(label)) {
+ count += facetsMap.get(label).getCount();
+ }
+ facetsMap.put(label, new Facet(label, count));
}
label = null;
}
}
+ facets = Lists.newArrayList(facetsMap.values());
+ Collections.sort(facets, new Comparator<Facet>() {
+ @Override
+ public int compare(Facet facet1, Facet facet2) {
+ int cnt1 = facet1.getCount();
+ int cnt2 = facet2.getCount();
+
+ if (cnt1 > cnt2) {
+ return -1;
+ } else if (cnt1 == cnt2) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+ });
perDimFacets.put(dimension, facets);
}
@@ -102,7 +172,7 @@ public class FacetResult {
private final String label;
private final int count;
- private Facet(String label, int count) {
+ Facet(String label, int count) {
this.label = label;
this.count = count;
}
@@ -124,5 +194,9 @@ public class FacetResult {
return count;
}
}
+
+ public interface FacetResultRow {
+ String getValue(String columnName) throws Exception;
+ }
}
Modified: jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/query/facet/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/query/facet/package-info.java?rev=1847255&r1=1847254&r2=1847255&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/query/facet/package-info.java (original)
+++ jackrabbit/oak/branches/1.6/oak-core/src/main/java/org/apache/jackrabbit/oak/query/facet/package-info.java Fri Nov 23 12:22:47 2018
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@Version("1.0")
+@Version("1.1.0")
@Export(optional = "provide:=true")
package org.apache.jackrabbit.oak.query.facet;
Added: jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/query/ResultRowImplTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/query/ResultRowImplTest.java?rev=1847255&view=auto
==============================================================================
--- jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/query/ResultRowImplTest.java (added)
+++ jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/query/ResultRowImplTest.java Fri Nov 23 12:22:47 2018
@@ -0,0 +1,55 @@
+/*
+ * 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;
+
+import com.google.common.collect.Maps;
+import org.apache.jackrabbit.oak.api.PropertyValue;
+import org.apache.jackrabbit.oak.api.Type;
+import org.junit.Test;
+
+import java.util.Map;
+
+import static org.apache.jackrabbit.oak.spi.query.PropertyValues.newString;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ResultRowImplTest {
+ @Test
+ public void mappedGetValue() {
+ Query query = mock(Query.class);
+ when(query.getColumnIndex("origCol")).thenReturn(0);
+ when(query.getColumnIndex("col1")).thenReturn(1);
+
+ PropertyValue[] origVals = new PropertyValue[]{newString("origVal"), newString("overriddenVal")};
+ ResultRowImpl orig = new ResultRowImpl(query, null, origVals, null, null);
+
+ Map<String, String> map = Maps.newHashMap();
+ map.put("col1", "val1");
+
+ ResultRowImpl mappedRow = ResultRowImpl.getMappingResultRow(orig, map);
+
+ assertEquals("origVal", mappedRow.getValue("origCol").getValue(Type.STRING));
+ assertEquals("val1", mappedRow.getValue("col1").getValue(Type.STRING));
+
+ PropertyValue[] mappedVals = mappedRow.getValues();
+ assertEquals(2, mappedVals.length);
+ assertEquals("origVal", mappedVals[0].getValue(Type.STRING));
+ assertEquals("val1", mappedVals[1].getValue(Type.STRING));
+ }
+}
Propchange: jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/query/ResultRowImplTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/query/facet/FacetResultTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/query/facet/FacetResultTest.java?rev=1847255&r1=1847254&r2=1847255&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/query/facet/FacetResultTest.java (original)
+++ jackrabbit/oak/branches/1.6/oak-core/src/test/java/org/apache/jackrabbit/oak/query/facet/FacetResultTest.java Fri Nov 23 12:22:47 2018
@@ -16,13 +16,22 @@
*/
package org.apache.jackrabbit.oak.query.facet;
+import com.google.common.collect.Maps;
+import org.apache.jackrabbit.oak.commons.json.JsopBuilder;
+import org.apache.jackrabbit.oak.query.facet.FacetResult.Facet;
+import org.apache.jackrabbit.oak.query.facet.FacetResult.FacetResultRow;
+import org.junit.Test;
+
import javax.jcr.Value;
import javax.jcr.query.QueryResult;
import javax.jcr.query.Row;
import javax.jcr.query.RowIterator;
+import java.util.List;
+import java.util.Map;
import org.junit.Test;
+import static org.apache.jackrabbit.oak.query.QueryImpl.REP_FACET;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -65,4 +74,142 @@ public class FacetResultTest {
assertEquals(1, facetResult.getFacets("jcr:title").get(1).getCount(), 0);
}
+ @Test
+ public void simpleMergeFacets() {
+ String r1c1Facet = json(f("l1", 2), f("l2", 1));
+ String r2c1Facet = json(f("l2", 4), f("l1", 1));
+
+ FacetResult merged = facet(new FacetColumn("x", r1c1Facet, r2c1Facet));
+
+ FacetResult expected = facet(new FacetColumn("x", json(f("l2", 5), f("l1", 3))));
+
+ verify(expected, merged);
+ }
+
+ @Test
+ public void uniqueLabelsMergeFacets() {
+ String r1c1Facet = json(f("l1", 1));
+ String r2c1Facet = json(f("l2", 2));
+
+ FacetResult merged = facet(new FacetColumn("x", r1c1Facet, r2c1Facet));
+
+ FacetResult expected = facet(new FacetColumn("x", json(f("l2", 2), f("l1", 1))));
+
+ verify(expected, merged);
+ }
+
+ @Test
+ public void multipleColumns() {
+ String r1c1Facet = json(f("l1", 1));
+ String r2c1Facet = json(f("l2", 2));
+
+ String r1c2Facet = json(f("m1", 2));
+ String r2c2Facet = json(f("m2", 1));
+
+ FacetResult merged = facet(
+ new FacetColumn("x", r1c1Facet, r2c1Facet),
+ new FacetColumn("y", r1c2Facet, r2c2Facet)
+ );
+
+ FacetResult expected = facet(
+ new FacetColumn("x", json(f("l2", 2), f("l1", 1))),
+ new FacetColumn("y", json(f("m1", 2), f("m2", 1)))
+ );
+
+ verify(expected, merged);
+ }
+
+ @Test
+ public void multipleColumnsWithNullColumns() {
+ String r2c1Facet = json(f("l1", 1));
+ String r1c2Facet = json(f("m1", 1));
+
+ FacetResult merged = facet(
+ new FacetColumn("x", null, r2c1Facet),
+ new FacetColumn("y", r1c2Facet, null)
+ );
+
+ FacetResult expected = facet(
+ new FacetColumn("x", json(f("l1", 1))),
+ new FacetColumn("y", json(f("m1", 1)))
+ );
+
+ verify(expected, merged);
+ }
+
+ private FacetResult facet(FacetColumn ... facetColumns) {
+ String[] colNames = new String[facetColumns.length];
+ colNames[0] = facetColumns[0].colName;
+
+ int numRows = facetColumns[0].facets.length;
+
+ for (int i = 1; i < facetColumns.length; i++) {
+ assertEquals("numRows for col num " + i + " wasn't same as first", numRows, facetColumns[i].facets.length);
+
+ colNames[i] = facetColumns[i].colName;
+ }
+
+ FacetResultRow[] facetResultRows = new FacetResultRow[numRows];
+
+ for (int i = 0; i < numRows; i++) {
+ final Map<String, String> columns = Maps.newHashMap();
+
+ for (FacetColumn col : facetColumns) {
+ columns.put(col.colName, col.facets[i]);
+ }
+
+ facetResultRows[i] = new FacetResultRow() {
+ final Map<String, String> cols = columns;
+ @Override
+ public String getValue(String columnName) {
+ return cols.get(columnName);
+ }
+ };
+ }
+
+ return new FacetResult(colNames, facetResultRows);
+ }
+
+ private static String json(Facet ... facets) {
+ JsopBuilder builder = new JsopBuilder();
+ builder.object();
+ for (Facet facet : facets) {
+ builder.key(facet.getLabel());
+ builder.value(facet.getCount());
+ }
+ builder.endObject();
+
+ return builder.toString();
+ }
+
+ private static class FacetColumn {
+ final String colName;
+ final String[] facets;
+
+ FacetColumn(String colName, String ... facets) {
+ this.colName = REP_FACET + "(" + colName + ")";
+ this.facets = facets;
+ }
+ }
+
+ private static Facet f(String label, int count) {
+ return new Facet(label, count);
+ }
+
+ private static void verify(FacetResult expected, FacetResult result) {
+ assertEquals("Dimension mismatch", expected.getDimensions(), result.getDimensions());
+
+ for (String dim : expected.getDimensions()) {
+ List<Facet> expectedFacets = expected.getFacets(dim);
+ List<Facet> resultFacets = result.getFacets(dim);
+
+ for (int i = 0; i < expectedFacets.size(); i++) {
+ Facet expectedFacet = expectedFacets.get(i);
+ Facet resultFacet = resultFacets.get(i);
+
+ assertEquals("label mismatch for dim " + dim, expectedFacet.getLabel(), resultFacet.getLabel());
+ assertEquals("count mismatch for dim " + dim, expectedFacet.getCount(), resultFacet.getCount());
+ }
+ }
+ }
}
\ No newline at end of file
Modified: jackrabbit/oak/branches/1.6/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/FacetTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.6/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/FacetTest.java?rev=1847255&r1=1847254&r2=1847255&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.6/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/FacetTest.java (original)
+++ jackrabbit/oak/branches/1.6/oak-lucene/src/test/java/org/apache/jackrabbit/oak/jcr/query/FacetTest.java Fri Nov 23 12:22:47 2018
@@ -29,6 +29,7 @@ import javax.jcr.query.RowIterator;
import javax.jcr.security.Privilege;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import com.google.common.collect.Maps;
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
@@ -38,6 +39,7 @@ import org.apache.jackrabbit.oak.query.f
import org.junit.After;
import org.junit.Before;
+import static com.google.common.collect.Sets.newHashSet;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.REINDEX_PROPERTY_NAME;
/**
@@ -778,6 +780,95 @@ public class FacetTest extends AbstractQ
assertEquals(2, rows.getSize());
}
+ public void testMergedFacetsOverUnionUniqueLabels() throws Exception {
+ Node n1 = testRootNode.addNode("node1");
+ n1.setProperty("text", "t1");
+ n1.setProperty("x", "x1");
+ n1.setProperty("name","Node1");
+
+ Node n2 = testRootNode.addNode("node2");
+ n2.setProperty("text", "t2");
+ n2.setProperty("x", "x2");
+ n2.setProperty("name","Node2");
+
+ Node n3 = testRootNode.addNode("node3");
+ n3.setProperty("text", "t3");
+ n3.setProperty("x", "x3");
+ n3.setProperty("name","Node3");
+ superuser.save();
+
+ String xpath = "//*[@name = 'Node1' or @text = 't2' or @x = 'x3']/(rep:facet(text))";
+
+ Query q = qm.createQuery(xpath, Query.XPATH);
+
+ QueryResult result = q.execute();
+ FacetResult facetResult = new FacetResult(result);
+
+ assertEquals("Unexpected dimensions", newHashSet("text"), facetResult.getDimensions());
+
+ List<FacetResult.Facet> facets = facetResult.getFacets("text");
+
+ Set<String> facetLabels = newHashSet();
+ for (FacetResult.Facet facet : facets) {
+ assertEquals("Unexpected facet count for " + facet.getLabel(), 1, facet.getCount());
+ facetLabels.add(facet.getLabel());
+ }
+
+ assertEquals("Unexpected facet labels", newHashSet("t1", "t2", "t3"), facetLabels);
+ }
+
+ public void testMergedFacetsOverUnionSummingCount() throws Exception {
+ // the distribution of nodes with t1 and t2 are intentionally across first and second set (below)
+ // put such that second condition turns facet count around
+
+ // first set of nodes matching first condition (x1 = v1)
+ Node n11 = testRootNode.addNode("node11");
+ n11.setProperty("text", "t1");
+ n11.setProperty("x1","v1");
+ Node n12 = testRootNode.addNode("node12");
+ n12.setProperty("text", "t1");
+ n12.setProperty("x1","v1");
+ Node n13 = testRootNode.addNode("node13");
+ n13.setProperty("text", "t2");
+ n13.setProperty("x1","v1");
+
+ // second set of nodes matching second condition (x2 = v2)
+ Node n21 = testRootNode.addNode("node21");
+ n21.setProperty("text", "t2");
+ n21.setProperty("x2","v2");
+ Node n22 = testRootNode.addNode("node22");
+ n22.setProperty("text", "t1");
+ n22.setProperty("x2","v2");
+ Node n23 = testRootNode.addNode("node23");
+ n23.setProperty("text", "t1");
+ n23.setProperty("x2","v2");
+ Node n24 = testRootNode.addNode("node24");
+ n24.setProperty("text", "t1");
+ n24.setProperty("x2","v2");
+
+ superuser.save();
+
+ String xpath = "//*[@x1 = 'v1' or @x2 = 'v2']/(rep:facet(text))";
+
+ Query q = qm.createQuery(xpath, Query.XPATH);
+
+ QueryResult result = q.execute();
+ FacetResult facetResult = new FacetResult(result);
+
+ assertEquals("Unexpected dimensions", newHashSet("text"), facetResult.getDimensions());
+
+ List<FacetResult.Facet> facets = facetResult.getFacets("text");
+ assertEquals("Incorrect facet label list size", 2, facets.size());
+
+ FacetResult.Facet facet = facets.get(0);
+ assertEquals("t1", facet.getLabel());
+ assertEquals(5, facet.getCount());
+
+ facet = facets.get(1);
+ assertEquals("t2", facet.getLabel());
+ assertEquals(2, facet.getCount());
+ }
+
public Node deny(Node node) throws RepositoryException {
AccessControlUtils.deny(node, "anonymous", Privilege.JCR_ALL);
return node;