bug 59814: clear evaluation workbook and evaluation sheet caches. Patch from Greg Woolsey.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1751836 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Javen O'Neal 2016-07-07 22:22:10 +00:00
parent 77da6237a4
commit 9539c626a9
13 changed files with 106 additions and 3 deletions

View File

@ -45,4 +45,8 @@ final class HSSFEvaluationSheet implements EvaluationSheet {
} }
return new HSSFEvaluationCell(cell, this); return new HSSFEvaluationCell(cell, this);
} }
public void clearAllCachedResultValues() {
// nothing to do
}
} }

View File

@ -64,6 +64,10 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E
_iBook = book.getWorkbook(); _iBook = book.getWorkbook();
} }
public void clearAllCachedResultValues() {
// nothing to do
}
@Override @Override
public HSSFName createName() { public HSSFName createName() {
return _uBook.createName(); return _uBook.createName();

View File

@ -30,4 +30,12 @@ public interface EvaluationSheet {
* @return <code>null</code> if there is no cell at the specified coordinates * @return <code>null</code> if there is no cell at the specified coordinates
*/ */
EvaluationCell getCell(int rowIndex, int columnIndex); EvaluationCell getCell(int rowIndex, int columnIndex);
/**
* Propagated from {@link EvaluationWorkbook#clearAllCachedResultValues()} to clear locally cached data.
*
* @see WorkbookEvaluator#clearAllCachedResultValues()
* @see EvaluationWorkbook#clearAllCachedResultValues()
*/
public void clearAllCachedResultValues();
} }

View File

@ -74,6 +74,13 @@ public interface EvaluationWorkbook {
Ptg[] getFormulaTokens(EvaluationCell cell); Ptg[] getFormulaTokens(EvaluationCell cell);
UDFFinder getUDFFinder(); UDFFinder getUDFFinder();
/**
* Propagated from {@link WorkbookEvaluator#clearAllCachedResultValues()} to clear locally cached data.
* Implementations must call the same method on all referenced {@link EvaluationSheet} instances, as well as clearing local caches.
* @see WorkbookEvaluator#clearAllCachedResultValues()
*/
public void clearAllCachedResultValues();
class ExternalSheet { class ExternalSheet {
private final String _workbookName; private final String _workbookName;
private final String _sheetName; private final String _sheetName;

View File

@ -208,6 +208,7 @@ public final class WorkbookEvaluator {
public void clearAllCachedResultValues() { public void clearAllCachedResultValues() {
_cache.clear(); _cache.clear();
_sheetIndexesBySheet.clear(); _sheetIndexesBySheet.clear();
_workbook.clearAllCachedResultValues();
} }
/** /**

View File

@ -101,6 +101,14 @@ final class ForkedEvaluationSheet implements EvaluationSheet {
return mewb.getSheetIndex(_masterSheet); return mewb.getSheetIndex(_masterSheet);
} }
/* (non-Javadoc)
* leave the map alone, if it needs resetting, reusing this class is probably a bad idea.
* @see org.apache.poi.ss.formula.EvaluationSheet#clearAllCachedResultValues()
*/
public void clearAllCachedResultValues() {
_masterSheet.clearAllCachedResultValues();
}
private static final class RowColKey implements Comparable<RowColKey>{ private static final class RowColKey implements Comparable<RowColKey>{
private final int _rowIndex; private final int _rowIndex;
private final int _columnIndex; private final int _columnIndex;

View File

@ -136,4 +136,12 @@ final class ForkedEvaluationWorkbook implements EvaluationWorkbook {
public UDFFinder getUDFFinder(){ public UDFFinder getUDFFinder(){
return _masterBook.getUDFFinder(); return _masterBook.getUDFFinder();
} }
/* (non-Javadoc)
* leave the map alone, if it needs resetting, reusing this class is probably a bad idea.
* @see org.apache.poi.ss.formula.EvaluationSheet#clearAllCachedResultValues()
*/
public void clearAllCachedResultValues() {
_masterBook.clearAllCachedResultValues();
}
} }

View File

@ -47,4 +47,8 @@ final class SXSSFEvaluationSheet implements EvaluationSheet {
} }
return new SXSSFEvaluationCell(cell, this); return new SXSSFEvaluationCell(cell, this);
} }
public void clearAllCachedResultValues() {
// nothing to do
}
} }

View File

@ -56,6 +56,10 @@ public abstract class BaseXSSFEvaluationWorkbook implements FormulaRenderingWork
_uBook = book; _uBook = book;
} }
public void clearAllCachedResultValues() {
_tableCache = null;
}
private int convertFromExternalSheetIndex(int externSheetIndex) { private int convertFromExternalSheetIndex(int externSheetIndex) {
return externSheetIndex; return externSheetIndex;
} }

View File

@ -41,6 +41,10 @@ final class XSSFEvaluationSheet implements EvaluationSheet {
return _xs; return _xs;
} }
public void clearAllCachedResultValues() {
_cellCache = null;
}
public EvaluationCell getCell(int rowIndex, int columnIndex) { public EvaluationCell getCell(int rowIndex, int columnIndex) {
// cache for performance: ~30% speedup due to caching // cache for performance: ~30% speedup due to caching
if (_cellCache == null) { if (_cellCache == null) {

View File

@ -40,6 +40,11 @@ public final class XSSFEvaluationWorkbook extends BaseXSSFEvaluationWorkbook {
super(book); super(book);
} }
public void clearAllCachedResultValues() {
super.clearAllCachedResultValues();
_sheetCache = null;
}
@Override @Override
public int getSheetIndex(EvaluationSheet evalSheet) { public int getSheetIndex(EvaluationSheet evalSheet) {
XSSFSheet sheet = ((XSSFEvaluationSheet)evalSheet).getXSSFSheet(); XSSFSheet sheet = ((XSSFEvaluationSheet)evalSheet).getXSSFSheet();

View File

@ -18,17 +18,22 @@
package org.apache.poi.ss.formula; package org.apache.poi.ss.formula;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.CellValue; import org.apache.poi.ss.usermodel.CellValue;
import org.apache.poi.ss.usermodel.FormulaEvaluator; import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Table; import org.apache.poi.ss.usermodel.Table;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.XSSFTestDataSamples; import org.apache.poi.xssf.XSSFTestDataSamples;
import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator; import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFTable;
import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Test; import org.junit.Test;
@ -63,8 +68,40 @@ public class TestStructuredReferences {
try { try {
final FormulaEvaluator eval = new XSSFFormulaEvaluator(wb); final FormulaEvaluator eval = new XSSFFormulaEvaluator(wb);
confirm(eval, wb.getSheet("Table").getRow(5).getCell(0), 49); final XSSFSheet tableSheet = wb.getSheet("Table");
confirm(eval, wb.getSheet("Formulas").getRow(0).getCell(0), 209); final XSSFSheet formulaSheet = wb.getSheet("Formulas");
confirm(eval, tableSheet.getRow(5).getCell(0), 49);
confirm(eval, formulaSheet.getRow(0).getCell(0), 209);
confirm(eval, formulaSheet.getRow(1).getCell(0), "one");
// test changing a table value, to see if the caches are properly cleared
// Issue 59814
// this test passes before the fix for 59814
tableSheet.getRow(1).getCell(1).setCellValue("ONEA");
confirm(eval, formulaSheet.getRow(1).getCell(0), "ONEA");
// test adding a row to a table, issue 59814
Row newRow = tableSheet.getRow(7);
if (newRow == null) newRow = tableSheet.createRow(7);
newRow.createCell(0, CellType.FORMULA).setCellFormula("\\_Prime.1[[#This Row],[@Number]]*\\_Prime.1[[#This Row],[@Number]]");
newRow.createCell(1, CellType.STRING).setCellValue("thirteen");
newRow.createCell(2, CellType.NUMERIC).setCellValue(13);
// update Table
final XSSFTable table = wb.getTable("\\_Prime.1");
final AreaReference newArea = new AreaReference(table.getStartCellReference(), new CellReference(table.getEndRowIndex() + 1, table.getEndColIndex()));
String newAreaStr = newArea.formatAsString();
table.getCTTable().setRef(newAreaStr);
table.getCTTable().getAutoFilter().setRef(newAreaStr);
table.updateHeaders();
table.updateReferences();
// these fail before the fix for 59814
confirm(eval, tableSheet.getRow(7).getCell(0), 13*13);
confirm(eval, formulaSheet.getRow(0).getCell(0), 209 + 13*13);
} finally { } finally {
wb.close(); wb.close();
} }
@ -78,4 +115,13 @@ public class TestStructuredReferences {
} }
assertEquals(expectedResult, cv.getNumberValue(), 0.0); assertEquals(expectedResult, cv.getNumberValue(), 0.0);
} }
private static void confirm(FormulaEvaluator fe, Cell cell, String expectedResult) {
fe.clearAllCachedResultValues();
CellValue cv = fe.evaluate(cell);
if (cv.getCellType() != CellType.STRING) {
fail("expected String cell type but got " + cv.formatAsString());
}
assertEquals(expectedResult, cv.getStringValue());
}
} }