]> source.dussan.org Git - poi.git/commitdiff
Bug 62993: XSSFEvaluationSheet now retrieves valid last row index from underlying...
authorVladislav Galas <gallon@apache.org>
Thu, 3 Jan 2019 00:08:52 +0000 (00:08 +0000)
committerVladislav Galas <gallon@apache.org>
Thu, 3 Jan 2019 00:08:52 +0000 (00:08 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1850212 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationSheet.java
src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFEvaluationSheet.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationSheet.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
src/ooxml/testcases/org/apache/poi/xssf/streaming/TestSXSSFEvaluationSheet.java [new file with mode: 0644]
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFEvaluationSheet.java
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFEvaluationSheet.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/usermodel/BaseTestXEvaluationSheet.java [new file with mode: 0644]

index 6d5729446ddca139af430f0adc0b29bfb6111c1a..d2d6927c82b16e4c6a9cc129a43081c574dbbbc4 100644 (file)
@@ -28,11 +28,9 @@ import org.apache.poi.util.Internal;
 final class HSSFEvaluationSheet implements EvaluationSheet {
 
     private final HSSFSheet _hs;
-    private int _lastDefinedRow = -1;
 
     public HSSFEvaluationSheet(HSSFSheet hs) {
         _hs = hs;
-        _lastDefinedRow = _hs.getLastRowNum();
     }
 
     public HSSFSheet getHSSFSheet() {
@@ -45,7 +43,7 @@ final class HSSFEvaluationSheet implements EvaluationSheet {
      */
     @Override
     public int getLastRowNum() {
-        return _lastDefinedRow;
+        return _hs.getLastRowNum();
     }
     
     @Override
@@ -66,6 +64,5 @@ final class HSSFEvaluationSheet implements EvaluationSheet {
      */    
     @Override
     public void clearAllCachedResultValues() {
-        _lastDefinedRow = _hs.getLastRowNum();
     }
 }
index 882150c9030a93b221a14f4b299487f186ee00a7..bb1d1f1698f6678e4b474b38014311b24f1f9aac 100644 (file)
@@ -27,11 +27,9 @@ import org.apache.poi.util.Internal;
 @Internal
 final class SXSSFEvaluationSheet implements EvaluationSheet {
     private final SXSSFSheet _xs;
-    private int _lastDefinedRow = -1;
 
     public SXSSFEvaluationSheet(SXSSFSheet sheet) {
         _xs = sheet;
-        _lastDefinedRow = _xs.getLastRowNum();
     }
 
     public SXSSFSheet getSXSSFSheet() {
@@ -44,7 +42,7 @@ final class SXSSFEvaluationSheet implements EvaluationSheet {
      */
     @Override
     public int getLastRowNum() {
-        return _lastDefinedRow;
+        return _xs.getLastRowNum();
     }
     
     @Override
@@ -68,6 +66,5 @@ final class SXSSFEvaluationSheet implements EvaluationSheet {
      */
     @Override
     public void clearAllCachedResultValues() {
-        _lastDefinedRow = _xs.getLastRowNum();
     }
 }
index c8c3b9d173838d276d6f14ed62a4aaf5e7810a3f..74ac23215a15c69f35876bd009edf930062d285a 100644 (file)
@@ -34,11 +34,9 @@ final class XSSFEvaluationSheet implements EvaluationSheet {
 
     private final XSSFSheet _xs;
     private Map<CellKey, EvaluationCell> _cellCache;
-    private int _lastDefinedRow = -1;
 
     public XSSFEvaluationSheet(XSSFSheet sheet) {
         _xs = sheet;
-        _lastDefinedRow = _xs.getLastRowNum();
     }
 
     public XSSFSheet getXSSFSheet() {
@@ -51,7 +49,7 @@ final class XSSFEvaluationSheet implements EvaluationSheet {
      */
     @Override
     public int getLastRowNum() {
-        return _lastDefinedRow;
+        return _xs.getLastRowNum();
     }
     
     /* (non-JavaDoc), inherit JavaDoc from EvaluationWorkbook
@@ -60,15 +58,16 @@ final class XSSFEvaluationSheet implements EvaluationSheet {
     @Override
     public void clearAllCachedResultValues() {
         _cellCache = null;
-        _lastDefinedRow = _xs.getLastRowNum();
     }
     
     @Override
     public EvaluationCell getCell(int rowIndex, int columnIndex) {
         // shortcut evaluation if reference is outside the bounds of existing data
         // see issue #61841 for impact on VLOOKUP in particular
-        if (rowIndex > _lastDefinedRow) return null;
-        
+        if (rowIndex > getLastRowNum()) {
+            return null;
+        }
+
         // cache for performance: ~30% speedup due to caching
         if (_cellCache == null) {
             _cellCache = new HashMap<>(_xs.getLastRowNum() * 3);
index 555968c42a5c616b87cc2962b0f505aab5452d31..d95decccef38602d1ec92858ef1229ea87cdb3ae 100644 (file)
@@ -27,7 +27,6 @@ import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
@@ -131,7 +130,6 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetViews;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTablePart;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableParts;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheetSource;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCalcMode;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellFormulaType;
 import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPane;
@@ -1211,6 +1209,10 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet  {
 
     @Override
     public int getLastRowNum() {
+        // _rows.getLastKey() (O(logN)) or caching last row (O(1))?
+        // A test with 1_000_000 rows shows that querying getLastRowNum with lastKey() implementation takes ~40 ms,
+        // and ~1.2 ms with cached implementation. 40 ms is negligible compared to the time of evaluation a million
+        // cells, and the lastKey implementation is much more elegant and less error prone than caching.
         return _rows.isEmpty() ? 0 : _rows.lastKey();
     }
 
diff --git a/src/ooxml/testcases/org/apache/poi/xssf/streaming/TestSXSSFEvaluationSheet.java b/src/ooxml/testcases/org/apache/poi/xssf/streaming/TestSXSSFEvaluationSheet.java
new file mode 100644 (file)
index 0000000..1c20bb8
--- /dev/null
@@ -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.poi.xssf.streaming;
+
+import org.apache.poi.ss.formula.EvaluationSheet;
+import org.apache.poi.ss.usermodel.BaseTestXEvaluationSheet;
+import org.apache.poi.ss.usermodel.Sheet;
+
+import java.util.AbstractMap;
+import java.util.Map;
+
+public class TestSXSSFEvaluationSheet extends BaseTestXEvaluationSheet {
+    @Override
+    protected Map.Entry<Sheet, EvaluationSheet> getInstance() {
+        SXSSFSheet sheet = new SXSSFWorkbook().createSheet();
+        return new AbstractMap.SimpleEntry<>(sheet, new SXSSFEvaluationSheet(sheet));
+    }
+}
index 1b1417fbb3dbb728e83c334d6629350d3fbeb76a..fdb85763617b52f8ab9c5b0e7e7ab5cb6d715ed6 100644 (file)
 ==================================================================== */
 package org.apache.poi.xssf.usermodel;
 
+import org.apache.poi.ss.formula.EvaluationSheet;
+import org.apache.poi.ss.usermodel.BaseTestXEvaluationSheet;
+import org.apache.poi.ss.usermodel.Sheet;
 import org.junit.Test;
 
+import java.util.AbstractMap;
+import java.util.Map;
+
 import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
-public class TestXSSFEvaluationSheet {
+public class TestXSSFEvaluationSheet extends BaseTestXEvaluationSheet {
 
     @Test
     public void test() throws Exception {
@@ -52,4 +60,10 @@ public class TestXSSFEvaluationSheet {
         // other things
         assertEquals(sheet, evalsheet.getXSSFSheet());
     }
-}
\ No newline at end of file
+
+    @Override
+    protected Map.Entry<Sheet, EvaluationSheet> getInstance() {
+        XSSFSheet sheet = new XSSFWorkbook().createSheet();
+        return new AbstractMap.SimpleEntry<>(sheet, new XSSFEvaluationSheet(sheet));
+    }
+}
diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFEvaluationSheet.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFEvaluationSheet.java
new file mode 100644 (file)
index 0000000..81700ae
--- /dev/null
@@ -0,0 +1,33 @@
+/* ====================================================================
+   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.poi.hssf.usermodel;
+
+import org.apache.poi.ss.formula.EvaluationSheet;
+import org.apache.poi.ss.usermodel.BaseTestXEvaluationSheet;
+import org.apache.poi.ss.usermodel.Sheet;
+
+import java.util.AbstractMap;
+import java.util.Map;
+
+public class TestHSSFEvaluationSheet extends BaseTestXEvaluationSheet {
+    @Override
+    protected Map.Entry<Sheet, EvaluationSheet> getInstance() {
+        HSSFSheet sheet = new HSSFWorkbook().createSheet();
+        return new AbstractMap.SimpleEntry<>(sheet, new HSSFEvaluationSheet(sheet));
+    }
+}
diff --git a/src/testcases/org/apache/poi/ss/usermodel/BaseTestXEvaluationSheet.java b/src/testcases/org/apache/poi/ss/usermodel/BaseTestXEvaluationSheet.java
new file mode 100644 (file)
index 0000000..cd60b3f
--- /dev/null
@@ -0,0 +1,49 @@
+/* ====================================================================
+   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.poi.ss.usermodel;
+
+import org.apache.poi.ss.formula.EvaluationSheet;
+import org.junit.Test;
+
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+public abstract class BaseTestXEvaluationSheet {
+    /**
+     * Get a pair of underlying sheet and evaluation sheet.
+     */
+    protected abstract Map.Entry<Sheet, EvaluationSheet> getInstance();
+
+    @Test
+    public void lastRowNumIsUpdatedFromUnderlyingSheet_bug62993() {
+        Map.Entry<Sheet, EvaluationSheet> sheetPair = getInstance();
+        Sheet underlyingSheet = sheetPair.getKey();
+        EvaluationSheet instance = sheetPair.getValue();
+
+        assertEquals(0, instance.getLastRowNum());
+
+        underlyingSheet.createRow(0);
+        underlyingSheet.createRow(1);
+        underlyingSheet.createRow(2);
+        assertEquals(2, instance.getLastRowNum());
+
+        underlyingSheet.removeRow(underlyingSheet.getRow(2));
+        assertEquals(1, instance.getLastRowNum());
+    }
+}