diff options
author | Dennis Francis <dennis.francis@collabora.co.uk> | 2018-01-23 19:53:19 +0530 |
---|---|---|
committer | Michael Meeks <michael.meeks@collabora.com> | 2018-01-24 12:25:13 +0100 |
commit | 1c6244f1faaefb6a5198c79c00849924ac2e91c2 (patch) | |
tree | b1e9c02150aeec2dcc4c92cdcaafee16b48bd085 | |
parent | ada232a67fbb3acf60b104a4916719dbdb891819 (diff) |
tdf#115093 : Do not reuse singleref tokens...
...in formula group computation if the formula contains
only a single reference besides any ocOpen/ocClose pairs
wrapping it as the sole content.
In such a case the "result" formula token
returned by ScInterpreter::GetResultToken() is the same
as the original singleref token, so for each row of the
formulagroup, we need to use a separate singleref token.
Also added a unit test in sc/qa/unit/parallelism.cxx
Change-Id: I6032efc5be9b51ca1e9daf9bdd19997a949d2f43
Reviewed-on: https://gerrit.libreoffice.org/48449
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Tested-by: Jenkins <ci@libreoffice.org>
(cherry picked from commit ff166845fa5ed178a97b54bb2deef4beb0cf3bdf)
Reviewed-on: https://gerrit.libreoffice.org/48478
Tested-by: Michael Meeks <michael.meeks@collabora.com>
-rw-r--r-- | sc/qa/unit/parallelism.cxx | 23 | ||||
-rw-r--r-- | sc/source/core/tool/formulagroup.cxx | 16 |
2 files changed, 36 insertions, 3 deletions
diff --git a/sc/qa/unit/parallelism.cxx b/sc/qa/unit/parallelism.cxx index 428d65a20bec..896b7c1d8382 100644 --- a/sc/qa/unit/parallelism.cxx +++ b/sc/qa/unit/parallelism.cxx @@ -46,12 +46,14 @@ public: void testDivision(); void testVLOOKUP(); void testVLOOKUPSUM(); + void testSingleRef(); CPPUNIT_TEST_SUITE(ScParallelismTest); CPPUNIT_TEST(testSUMIFS); CPPUNIT_TEST(testDivision); CPPUNIT_TEST(testVLOOKUP); CPPUNIT_TEST(testVLOOKUPSUM); + CPPUNIT_TEST(testSingleRef); CPPUNIT_TEST_SUITE_END(); private: @@ -296,6 +298,27 @@ void ScParallelismTest::testVLOOKUPSUM() m_pDoc->DeleteTab(0); } +void ScParallelismTest::testSingleRef() +{ + m_pDoc->InsertTab(0, "1"); + + const size_t nNumRows = 200; + for (size_t i = 0; i < nNumRows; ++i) + { + m_pDoc->SetValue(0, i, 0, static_cast<double>(i)); + m_pDoc->SetFormula(ScAddress(1, i, 0), "=A" + OUString::number(i+1), formula::FormulaGrammar::GRAM_NATIVE_UI); + } + + m_xDocShell->DoHardRecalc(); + + for (size_t i = 0; i < nNumRows; ++i) + { + OString aMsg = "At row " + OString::number(i); + CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg.getStr(), i, static_cast<size_t>(m_pDoc->GetValue(1, i, 0))); + } + m_pDoc->DeleteTab(0); +} + CPPUNIT_TEST_SUITE_REGISTRATION(ScParallelismTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx index d763d15d2f1c..38b9c2a327ee 100644 --- a/sc/source/core/tool/formulagroup.cxx +++ b/sc/source/core/tool/formulagroup.cxx @@ -177,6 +177,7 @@ public: ScTokenArray aCode2; ScInterpreterContext aContext(mrDoc, mpFormatter); + sal_uInt16 nNumNonOpenClose = mrCode.GetLen(); for (SCROW i = mnIdx; i <= mnLastIdx; ++i, maBatchTopPos.IncRow()) { @@ -212,7 +213,7 @@ public: aCode2.AddString(rPool.intern(OUString(pStr))); else { - if ( pTargetTok->GetType() == formula::svString ) + if ( ( pTargetTok->GetType() == formula::svString ) && ( nNumNonOpenClose > 1 ) ) pTargetTok->SetString(rPool.intern(OUString(pStr))); else { @@ -226,7 +227,7 @@ public: // Value of NaN represents an empty cell. if ( !pTargetTok ) aCode2.AddToken(ScEmptyCellToken(false, false)); - else if ( pTargetTok->GetType() != formula::svEmptyCell ) + else if ( ( pTargetTok->GetType() != formula::svEmptyCell ) || ( nNumNonOpenClose == 1 ) ) { ScEmptyCellToken* pEmptyTok = new ScEmptyCellToken(false, false); aCode2.ReplaceToken(nTokIdx, pEmptyTok, formula::FormulaTokenArray::CODE_ONLY); @@ -239,7 +240,7 @@ public: aCode2.AddDouble(fVal); else { - if ( pTargetTok->GetType() == formula::svDouble ) + if ( ( pTargetTok->GetType() == formula::svDouble ) && ( nNumNonOpenClose > 1 ) ) pTargetTok->GetDoubleAsReference() = fVal; else { @@ -291,7 +292,16 @@ public: break; default: if ( !pTargetTok ) + { + if ( p->GetType() == formula::svSep ) + { + OpCode eOp = p->GetOpCode(); + if ( eOp == ocOpen || eOp == ocClose ) + --nNumNonOpenClose; + } + aCode2.AddToken(*p); + } } // end of switch statement } // end of formula token for loop |