jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From thom...@apache.org
Subject svn commit: r1667318 - in /jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene: QueryResultImpl.java SearchIndex.java
Date Tue, 17 Mar 2015 14:51:32 GMT
Author: thomasm
Date: Tue Mar 17 14:51:31 2015
New Revision: 1667318

URL: http://svn.apache.org/r1667318
Log:
JCR-3858 NodeIterator.getSize(): compatibility with Jackrabbit 2.5

Modified:
    jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java
    jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java

Modified: jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java?rev=1667318&r1=1667317&r2=1667318&view=diff
==============================================================================
--- jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java
(original)
+++ jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryResultImpl.java
Tue Mar 17 14:51:31 2015
@@ -119,6 +119,8 @@ public abstract class QueryResultImpl im
      * The maximum size of this result if limit >= 0
      */
     private final long limit;
+    
+    private final boolean sizeEstimate;
 
     /**
      * Creates a new query result. The concrete sub class is responsible for
@@ -146,6 +148,7 @@ public abstract class QueryResultImpl im
             ColumnImpl[] columns, boolean documentOrder,
             long offset, long limit) throws RepositoryException {
         this.index = index;
+        this.sizeEstimate = index.getSizeEstimate();
         this.sessionContext = sessionContext;
         this.queryImpl = queryImpl;
         this.spellSuggestion = spellSuggestion;
@@ -258,10 +261,12 @@ public abstract class QueryResultImpl im
             log.debug("getResults({}) limit={}", size, limit);
         }
         
-        // quick check
-        // if numResults is set, all relevant results have been fetched
-        if (numResults != -1) {
-            return;
+        if (!sizeEstimate) {
+            // quick check
+            // if numResults is set, all relevant results have been fetched
+            if (numResults != -1) {
+                return;
+            }
         }
 
         long maxResultSize = size;
@@ -291,7 +296,11 @@ public abstract class QueryResultImpl im
             List<ScoreNode[]> offsetNodes = new ArrayList<ScoreNode[]>();
             if (resultNodes.isEmpty() && offset > 0) {
                 // collect result offset into dummy list
-                collectScoreNodes(result, offsetNodes, offset);
+                if (sizeEstimate) {
+                    collectScoreNodes(result, new ArrayList<ScoreNode[]>(), offset);
                   
+                } else {
+                    collectScoreNodes(result, offsetNodes, offset);
+                }
             } else {
                 int start = resultNodes.size() + invalid + (int) offset;
                 result.skip(start);
@@ -303,24 +312,29 @@ public abstract class QueryResultImpl im
             log.debug("retrieved ScoreNodes in {} ms ({})",
                     System.currentTimeMillis() - time, r3 - r2);
 
-            // update numResults if all results have been fetched 
-            // if resultNodes.getSize() is strictly smaller than maxResultSize, it means
that all results have been fetched
-            int resultSize = resultNodes.size();
-            if (resultSize < maxResultSize) {
-                if (resultNodes.isEmpty()) {
-                    // if there's no result nodes, the actual totalResults if smaller or
equals than the offset
-                    totalResults = offsetNodes.size();
-                    numResults = 0;
+            if (sizeEstimate) {
+                // update numResults
+                numResults = result.getSize();                
+            } else {
+                // update numResults if all results have been fetched 
+                // if resultNodes.getSize() is strictly smaller than maxResultSize, it means
that all results have been fetched
+                int resultSize = resultNodes.size();
+                if (resultSize < maxResultSize) {
+                    if (resultNodes.isEmpty()) {
+                        // if there's no result nodes, the actual totalResults if smaller
or equals than the offset
+                        totalResults = offsetNodes.size();
+                        numResults = 0;
+                    }
+                    else {
+                        totalResults = resultSize + (int) offset;
+                        numResults = resultSize;
+                    }
                 }
-                else {
-                    totalResults = resultSize + (int) offset;
-                    numResults = resultSize;
+                else if (resultSize == limit) {
+                    // if there's "limit" results, we can't know the total size (which may
be greater), but the result size is the limit
+                    numResults = (int) limit;
                 }
             }
-            else if (resultSize == limit) {
-                // if there's "limit" results, we can't know the total size (which may be
greater), but the result size is the limit
-                numResults = (int) limit;
-            }
         } catch (IOException e) {
             throw new RepositoryException(e);
         } finally {
@@ -393,11 +407,23 @@ public abstract class QueryResultImpl im
      * will get get if you don't set any limit or offset. This method may return
      * <code>-1</code> if the total size is unknown.
      * <p>
+     * If the "sizeEstimate" options is enabled:
+     * Keep in mind that this number may get smaller if nodes are found in
+     * the result set which the current session has no permission to access.
+     * This might be a security problem.
      *
      * @return the total number of hits.
      */
     public int getTotalSize() {
-        return totalResults;
+        if (sizeEstimate) {
+            if (numResults == -1) {
+                return -1;
+            } else {
+                return numResults - invalid;
+            }
+        } else {
+            return totalResults;
+        }
     }
 
     private final class LazyScoreNodeIteratorImpl implements ScoreNodeIterator {
@@ -448,9 +474,26 @@ public abstract class QueryResultImpl im
 
         /**
          * {@inheritDoc}
+         * <p/>
+         * If the "sizeEstimate" options is enabled:
+         * This value may shrink when the query result encounters non-existing
+         * nodes or the session does not have access to a node.
          */
         public long getSize() {
-            return numResults;
+            if (sizeEstimate) {
+                int total = getTotalSize();
+                if (total == -1) {
+                    return -1;
+                }
+                long size = offset > total ? 0 : total - offset;
+                if (limit >= 0 && size > limit) {
+                    return limit;
+                } else {
+                    return size;
+                }                
+            } else {
+                return numResults;
+            }
         }
 
         /**
@@ -504,9 +547,16 @@ public abstract class QueryResultImpl im
             while (next == null) {
                 if (nextPos >= resultNodes.size()) {
                     // quick check if there are more results at all
-                    // if numResults is set, all relevant results have been fetched
-                    if (numResults != -1) {
-                        break;
+                    if (sizeEstimate) {
+                        // this check is only possible if we have numResults
+                        if (numResults != -1 && (nextPos + invalid) >= numResults)
{
+                            break;
+                        }
+                    } else {
+                        // if numResults is set, all relevant results have been fetched
+                        if (numResults != -1) {
+                            break;
+                        }
                     }
 
                     // fetch more results

Modified: jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java?rev=1667318&r1=1667317&r2=1667318&view=diff
==============================================================================
--- jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
(original)
+++ jackrabbit/branches/2.6/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
Tue Mar 17 14:51:31 2015
@@ -386,6 +386,14 @@ public class SearchIndex extends Abstrac
      * Default value is: <code>false</code>.
      */
     private boolean supportHighlighting = false;
+    
+    /**
+     * If enabled, NodeIterator.getSize() may report a larger value than the
+     * actual result. This value may shrink when the query result encounters
+     * non-existing nodes or the session does not have access to a node. This
+     * might be a security problem.
+     */
+    private boolean sizeEstimate = false;
 
     /**
      * The excerpt provider class. Implements {@link ExcerptProvider}.
@@ -2178,6 +2186,30 @@ public class SearchIndex extends Abstrac
     public long getExtractorTimeout() {
         return extractorTimeout;
     }
+    
+    /**
+     * If enabled, NodeIterator.getSize() may report a larger value than the
+     * actual result. This value may shrink when the query result encounters
+     * non-existing nodes or the session does not have access to a node. This
+     * might be a security problem.
+     * 
+     * @param b <code>true</code> to enable
+     */
+    public void setSizeEstimate(boolean b) {
+        if (b) {
+            log.info("Size estimation is enabled");
+        }
+        this.sizeEstimate = b;
+    }
+    
+    /**
+     * Get the size estimate setting.
+     * 
+     * @return the setting
+     */
+    public boolean getSizeEstimate() {
+        return sizeEstimate;
+    }
 
     /**
      * If set to <code>true</code> additional information is stored in the index



Mime
View raw message