summaryrefslogtreecommitdiff
path: root/sc/source/core/tool
diff options
context:
space:
mode:
authorKohei Yoshida <kyoshida@novell.com>2009-09-09 10:57:16 -0400
committerKohei Yoshida <kyoshida@novell.com>2009-09-09 10:57:16 -0400
commit5a9783e305852ab2cd3ef81b04df6d552fec7730 (patch)
tree9cd37a34def8e195f582169a9c0b30895524e9ba /sc/source/core/tool
parent7cc7de904e47f2d0b5c68171b27fc66fc1415158 (diff)
#i102750# initial refactoring in an effort to support external references in DSUM, DGET etc. Not finished yet.
Diffstat (limited to 'sc/source/core/tool')
-rw-r--r--sc/source/core/tool/dbcolect.cxx1
-rw-r--r--sc/source/core/tool/doubleref.cxx236
-rw-r--r--sc/source/core/tool/interpr1.cxx226
-rw-r--r--sc/source/core/tool/interpr4.cxx89
-rw-r--r--sc/source/core/tool/makefile.mk4
-rw-r--r--sc/source/core/tool/queryparam.cxx296
6 files changed, 749 insertions, 103 deletions
diff --git a/sc/source/core/tool/dbcolect.cxx b/sc/source/core/tool/dbcolect.cxx
index 51120a106..7bf0a108b 100644
--- a/sc/source/core/tool/dbcolect.cxx
+++ b/sc/source/core/tool/dbcolect.cxx
@@ -40,6 +40,7 @@
#include "refupdat.hxx"
#include "rechead.hxx"
#include "document.hxx"
+#include "queryparam.hxx"
#include "globstr.hrc"
diff --git a/sc/source/core/tool/doubleref.cxx b/sc/source/core/tool/doubleref.cxx
new file mode 100644
index 000000000..218931ffe
--- /dev/null
+++ b/sc/source/core/tool/doubleref.cxx
@@ -0,0 +1,236 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: interpre.hxx,v $
+ * $Revision: 1.35.44.2 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "doubleref.hxx"
+#include "cell.hxx"
+#include "global.hxx"
+#include "document.hxx"
+#include "queryparam.hxx"
+
+using ::rtl::OUString;
+
+// ============================================================================
+
+ScDoubleRefBase::ScDoubleRefBase(ScDocument* pDoc, RefType eType) :
+ mpDoc(pDoc), meType(eType)
+{
+}
+
+ScDoubleRefBase::~ScDoubleRefBase()
+{
+}
+
+ScDoubleRefBase::RefType ScDoubleRefBase::getType() const
+{
+ return meType;
+}
+
+ScDocument* ScDoubleRefBase::getDoc()
+{
+ return mpDoc;
+}
+
+// ============================================================================
+
+ScInternalDoubleRef::ScInternalDoubleRef(ScDocument* pDoc, const ScRange& rRange) :
+ ScDoubleRefBase(pDoc, INTERNAL), maRange(rRange)
+{
+}
+
+ScInternalDoubleRef::~ScInternalDoubleRef()
+{
+}
+
+const ScRange& ScInternalDoubleRef::getRange() const
+{
+ return maRange;
+}
+
+SCCOL ScInternalDoubleRef::getFirstFieldColumn()
+{
+ return getRange().aStart.Col();
+}
+
+SCCOL ScInternalDoubleRef::findFieldColumn(SCCOL nColIndex)
+{
+ const ScRange& rRange = getRange();
+ const ScAddress& s = rRange.aStart;
+ const ScAddress& e = rRange.aEnd;
+
+ SCCOL nDBCol1 = s.Col();
+ SCCOL nDBCol2 = e.Col();
+
+ if ( nColIndex <= 0 || nColIndex > (nDBCol2 - nDBCol1 + 1) )
+ return nDBCol1;
+
+ return Min(nDBCol2, static_cast<SCCOL>(nDBCol1 + nColIndex - 1));
+}
+
+sal_uInt16 ScInternalDoubleRef::getCellString(String& rStr, ScBaseCell* pCell)
+{
+ sal_uInt16 nErr = 0;
+ if (pCell)
+ {
+ SvNumberFormatter* pFormatter = getDoc()->GetFormatTable();
+ switch (pCell->GetCellType())
+ {
+ case CELLTYPE_STRING:
+ ((ScStringCell*) pCell)->GetString(rStr);
+ break;
+ case CELLTYPE_EDIT:
+ ((ScEditCell*) pCell)->GetString(rStr);
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ ScFormulaCell* pFCell = (ScFormulaCell*) pCell;
+ nErr = pFCell->GetErrCode();
+ if (pFCell->IsValue())
+ {
+ double fVal = pFCell->GetValue();
+ ULONG nIndex = pFormatter->GetStandardFormat(
+ NUMBERFORMAT_NUMBER,
+ ScGlobal::eLnge);
+ pFormatter->GetInputLineString(fVal, nIndex, rStr);
+ }
+ else
+ pFCell->GetString(rStr);
+ }
+ break;
+ case CELLTYPE_VALUE:
+ {
+ double fVal = ((ScValueCell*) pCell)->GetValue();
+ ULONG nIndex = pFormatter->GetStandardFormat(
+ NUMBERFORMAT_NUMBER,
+ ScGlobal::eLnge);
+ pFormatter->GetInputLineString(fVal, nIndex, rStr);
+ }
+ break;
+ default:
+ rStr = ScGlobal::GetEmptyString();
+ break;
+ }
+ }
+ else
+ rStr = ScGlobal::GetEmptyString();
+
+ return nErr;
+}
+
+SCCOL ScInternalDoubleRef::findFieldColumn(const OUString& rStr, sal_uInt16& rErr)
+{
+ const ScRange& rRange = getRange();
+ const ScAddress& s = rRange.aStart;
+ const ScAddress& e = rRange.aEnd;
+
+ SCCOL nDBCol1 = s.Col();
+ SCROW nDBRow1 = s.Row();
+ SCTAB nDBTab1 = s.Tab();
+ SCCOL nDBCol2 = e.Col();
+
+ SCCOL nField = nDBCol1;
+ BOOL bFound = TRUE;
+
+ bFound = FALSE;
+ String aCellStr;
+ ScAddress aLook( nDBCol1, nDBRow1, nDBTab1 );
+ while (!bFound && (aLook.Col() <= nDBCol2))
+ {
+ ScBaseCell* pCell = getDoc()->GetCell( aLook );
+ rErr = getCellString( aCellStr, pCell );
+ bFound = ScGlobal::pTransliteration->isEqual(aCellStr, rStr);
+ if (!bFound)
+ aLook.IncCol();
+ }
+ nField = aLook.Col();
+
+ return bFound ? nField : -1;
+}
+
+void ScInternalDoubleRef::initQueryParam(ScQueryParam& rParam) const
+{
+ const ScAddress& s = maRange.aStart;
+ const ScAddress& e = maRange.aEnd;
+ rParam.nCol1 = s.Col();
+ rParam.nRow1 = s.Row();
+ rParam.nCol2 = e.Col();
+ rParam.nRow2 = e.Row();
+ rParam.nTab = s.Tab();
+ rParam.bHasHeader = TRUE;
+ rParam.bByRow = TRUE;
+ rParam.bInplace = TRUE;
+ rParam.bCaseSens = FALSE;
+ rParam.bRegExp = FALSE;
+ rParam.bDuplicate = TRUE;
+}
+
+bool ScInternalDoubleRef::isRangeEqual(const ScRange& rRange) const
+{
+ return maRange == rRange;
+}
+
+// ============================================================================
+
+ScExternalDoubleRef::ScExternalDoubleRef(ScDocument* pDoc) :
+ ScDoubleRefBase(pDoc, EXTERNAL)
+{
+}
+
+ScExternalDoubleRef::~ScExternalDoubleRef()
+{
+}
+
+SCCOL ScExternalDoubleRef::getFirstFieldColumn()
+{
+ return -1;
+}
+
+SCCOL ScExternalDoubleRef::findFieldColumn(SCCOL nColIndex)
+{
+ return -1;
+}
+
+SCCOL ScExternalDoubleRef::findFieldColumn(const OUString& rStr, sal_uInt16& rErr)
+{
+ return -1;
+}
+
+void ScExternalDoubleRef::initQueryParam(ScQueryParam& rParam) const
+{
+}
+
+bool ScExternalDoubleRef::isRangeEqual(const ScRange& /*rRange*/) const
+{
+ return false;
+}
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 1007f7ed3..1e45a973e 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -67,14 +67,54 @@
#include <string.h>
#include <math.h>
#include <vector>
+#include <memory>
#include "cellkeytranslator.hxx"
#include "lookupcache.hxx"
#include "rangenam.hxx"
#include "compiler.hxx"
#include "externalrefmgr.hxx"
+#include "doubleref.hxx"
+#include "queryparam.hxx"
#define SC_DOUBLE_MAXVALUE 1.7e307
+
+#include <stdio.h>
+#include <string>
+#include <sys/time.h>
+
+namespace {
+
+class StackPrinter
+{
+public:
+ explicit StackPrinter(const char* msg) :
+ msMsg(msg)
+ {
+ fprintf(stdout, "%s: --begin\n", msMsg.c_str());
+ mfStartTime = getTime();
+ }
+
+ ~StackPrinter()
+ {
+ double fEndTime = getTime();
+ fprintf(stdout, "%s: --end (duration: %g sec)\n", msMsg.c_str(), (fEndTime-mfStartTime));
+ }
+
+private:
+ double getTime() const
+ {
+ timeval tv;
+ gettimeofday(&tv, NULL);
+ return tv.tv_sec + tv.tv_usec / 1000000.0;
+ }
+
+ ::std::string msMsg;
+ double mfStartTime;
+};
+
+}
+
IMPL_FIXEDMEMPOOL_NEWDEL( ScTokenStack, 8, 4 )
IMPL_FIXEDMEMPOOL_NEWDEL( ScInterpreter, 32, 16 )
@@ -5618,9 +5658,9 @@ void ScInterpreter::ScSubTotal()
#endif
-BOOL ScInterpreter::GetDBParams(SCTAB& rTab, ScQueryParam& rParam,
- BOOL& rMissingField )
+BOOL ScInterpreter::GetDBParams( ScQueryParam& rParam, BOOL& rMissingField )
{
+ StackPrinter __stack_printer__("ScInterpreter::GetDBParams");
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::GetDBParams" );
BOOL bRet = FALSE;
BOOL bAllowMissingField = FALSE;
@@ -5631,14 +5671,10 @@ BOOL ScInterpreter::GetDBParams(SCTAB& rTab, ScQueryParam& rParam,
}
if ( GetByte() == 3 )
{
-
- SCCOL nQCol1;
- SCROW nQRow1;
- SCTAB nQTab1;
- SCCOL nQCol2;
- SCROW nQRow2;
- SCTAB nQTab2;
- PopDoubleRef(nQCol1, nQRow1, nQTab1, nQCol2, nQRow2, nQTab2);
+ // First, get the query criteria range.
+ ::std::auto_ptr<ScDoubleRefBase> pQueryRef( PopDoubleRef() );
+ if (!pQueryRef.get())
+ return false;
BOOL bByVal = TRUE;
double nVal = 0.0;
@@ -5648,16 +5684,20 @@ BOOL ScInterpreter::GetDBParams(SCTAB& rTab, ScQueryParam& rParam,
switch (GetStackType())
{
case svDouble :
+ fprintf(stdout, "ScInterpreter::GetDBParams: double\n");
nVal = ::rtl::math::approxFloor( GetDouble() );
+ fprintf(stdout, "ScInterpreter::GetDBParams: value = %g\n", nVal);
if ( bAllowMissingField && nVal == 0.0 )
rMissingField = TRUE; // fake missing parameter
break;
case svString :
bByVal = FALSE;
aStr = GetString();
+ fprintf(stdout, "ScInterpreter::GetDBParams: str = '%s'\n", rtl::OUStringToOString(aStr, RTL_TEXTENCODING_UTF8).getStr());
break;
case svSingleRef :
{
+ fprintf(stdout, "ScInterpreter::GetDBParams: single ref\n");
ScAddress aAdr;
PopSingleRef( aAdr );
ScBaseCell* pCell = GetCell( aAdr );
@@ -5671,6 +5711,7 @@ BOOL ScInterpreter::GetDBParams(SCTAB& rTab, ScQueryParam& rParam,
}
break;
case svDoubleRef :
+ fprintf(stdout, "ScInterpreter::GetDBParams: double ref\n");
if ( bAllowMissingField )
{ // fake missing parameter for old SO compatibility
bRangeFake = TRUE;
@@ -5683,6 +5724,7 @@ BOOL ScInterpreter::GetDBParams(SCTAB& rTab, ScQueryParam& rParam,
}
break;
case svMissing :
+ fprintf(stdout, "ScInterpreter::GetDBParams: missing\n");
PopError();
if ( bAllowMissingField )
rMissingField = TRUE;
@@ -5690,98 +5732,74 @@ BOOL ScInterpreter::GetDBParams(SCTAB& rTab, ScQueryParam& rParam,
SetError( errIllegalParameter );
break;
default:
+ fprintf(stdout, "ScInterpreter::GetDBParams: pop error (%d)\n", __LINE__);
PopError();
SetError( errIllegalParameter );
}
- SCCOL nDBCol1;
- SCROW nDBRow1;
- SCTAB nDBTab1;
- SCCOL nDBCol2;
- SCROW nDBRow2;
- SCTAB nDBTab2;
- PopDoubleRef(nDBCol1, nDBRow1, nDBTab1, nDBCol2, nDBRow2, nDBTab2);
+ ::std::auto_ptr<ScDoubleRefBase> pDBRef( PopDoubleRef() );
- if ( nGlobalError == 0 && bRangeFake )
+ if (nGlobalError || !pDBRef.get())
+ return false;
+
+ if ( bRangeFake )
{
// range parameter must match entire database range
- if ( aMissingRange == ScRange( nDBCol1, nDBRow1, nDBTab1, nDBCol2,
- nDBRow2, nDBTab2) )
+ if (pDBRef->isRangeEqual(aMissingRange))
rMissingField = TRUE;
else
SetError( errIllegalParameter );
}
- if (nGlobalError == 0)
+ if (nGlobalError)
+ return false;
+
+ SCCOL nField = pDBRef->getFirstFieldColumn();
+ if (rMissingField)
+ ; // special case
+ else if (bByVal)
+ nField = pDBRef->findFieldColumn(static_cast<SCCOL>(nVal));
+ else
{
- SCCOL nField = nDBCol1;
- BOOL bFound = TRUE;
+ sal_uInt16 nErr = 0;
+ nField = pDBRef->findFieldColumn(aStr, nErr);
+ SetError(nErr);
+ }
+
+ if (!ValidCol(nField))
+ return false;
+
+ pDBRef->initQueryParam(rParam);
+ bool bCreated = pDok->CreateQueryParam(pQueryRef.get(), rParam);
+
+ if (bCreated)
+ {
+ fprintf(stdout, "ScInterpreter::GetDBParams: query param created\n");
+ // An allowed missing field parameter sets the result field
+ // to any of the query fields, just to be able to return
+ // some cell from the iterator.
if ( rMissingField )
- ; // special case
- else if ( bByVal )
- {
- if ( nVal <= 0 || nVal > (nDBCol2 - nDBCol1 + 1) )
- bFound = FALSE;
- else
- nField = Min(nDBCol2, (SCCOL)(nDBCol1 + (SCCOL)nVal - 1));
- }
- else
+ nField = static_cast<SCCOL>(rParam.GetEntry(0).nField);
+
+ rParam.nCol1 = nField;
+ rParam.nCol2 = nField;
+
+ SCSIZE nCount = rParam.GetEntryCount();
+ for ( SCSIZE i=0; i < nCount; i++ )
{
- bFound = FALSE;
- String aCellStr;
- ScAddress aLook( nDBCol1, nDBRow1, nDBTab1 );
- while (!bFound && (aLook.Col() <= nDBCol2))
- {
- ScBaseCell* pCell = GetCell( aLook );
- GetCellString( aCellStr, pCell );
- bFound = ScGlobal::pTransliteration->isEqual( aCellStr, aStr );
- if (!bFound)
- aLook.IncCol();
- }
- nField = aLook.Col();
- }
- if (bFound)
- {
- rParam.nCol1 = nDBCol1;
- rParam.nRow1 = nDBRow1;
- rParam.nCol2 = nDBCol2;
- rParam.nRow2 = nDBRow2;
- rParam.nTab = nDBTab1;
- rParam.bHasHeader = TRUE;
- rParam.bByRow = TRUE;
- rParam.bInplace = TRUE;
- rParam.bCaseSens = FALSE;
- rParam.bRegExp = FALSE;
- rParam.bDuplicate = TRUE;
- if (pDok->CreateQueryParam(nQCol1, nQRow1, nQCol2, nQRow2, nQTab1, rParam))
- {
- // An allowed missing field parameter sets the result field
- // to any of the query fields, just to be able to return
- // some cell from the iterator.
- if ( rMissingField )
- nField = static_cast<SCCOL>(rParam.GetEntry(0).nField);
-
- rParam.nCol1 = nField;
- rParam.nCol2 = nField;
- rTab = nDBTab1;
- bRet = TRUE;
- SCSIZE nCount = rParam.GetEntryCount();
- for ( SCSIZE i=0; i < nCount; i++ )
- {
- ScQueryEntry& rEntry = rParam.GetEntry(i);
- if ( rEntry.bDoQuery )
- {
- sal_uInt32 nIndex = 0;
- rEntry.bQueryByString = !pFormatter->IsNumberFormat(
- *rEntry.pStr, nIndex, rEntry.nVal );
- if ( rEntry.bQueryByString && !rParam.bRegExp )
- rParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
- }
- else
- break; // for
- }
+ ScQueryEntry& rEntry = rParam.GetEntry(i);
+ if ( rEntry.bDoQuery )
+ {
+ sal_uInt32 nIndex = 0;
+ rEntry.bQueryByString = !pFormatter->IsNumberFormat(
+ *rEntry.pStr, nIndex, rEntry.nVal );
+ if ( rEntry.bQueryByString && !rParam.bRegExp )
+ rParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
}
+ else
+ break; // for
}
+ bRet = true;
}
}
return bRet;
@@ -5790,19 +5808,21 @@ BOOL ScInterpreter::GetDBParams(SCTAB& rTab, ScQueryParam& rParam,
void ScInterpreter::DBIterator( ScIterFunc eFunc )
{
+ StackPrinter __stack_printer__("ScInterpreter::DBIterator");
+
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::DBIterator" );
- SCTAB nTab1;
double nErg = 0.0;
double fMem = 0.0;
BOOL bNull = TRUE;
ULONG nCount = 0;
- ScQueryParam aQueryParam;
+ ::std::auto_ptr<ScQueryParam> pQueryParam(new ScQueryParam);
BOOL bMissingField = FALSE;
- if ( GetDBParams( nTab1, aQueryParam, bMissingField) )
+ if ( GetDBParams( *pQueryParam, bMissingField) )
{
+ fprintf(stdout, "ScInterpreter::DBIterator: dp param is good\n");
double nVal;
USHORT nErr;
- ScQueryValueIterator aValIter(pDok, nTab1, aQueryParam);
+ ScQueryValueIterator aValIter(pDok, pQueryParam.release());
if ( aValIter.GetFirst(nVal, nErr) && !nErr )
{
switch( eFunc )
@@ -5836,10 +5856,14 @@ void ScInterpreter::DBIterator( ScIterFunc eFunc )
}
while ( aValIter.GetNext(nVal, nErr) && !nErr );
}
+ fprintf(stdout, "ScInterpreter::DBIterator: error = %d\n", nErr);
SetError(nErr);
}
else
+ {
+ fprintf(stdout, "ScInterpreter::DBIterator: dp params failed!\n");
SetError( errIllegalParameter);
+ }
switch( eFunc )
{
case ifCOUNT: nErg = nCount; break;
@@ -5853,6 +5877,7 @@ void ScInterpreter::DBIterator( ScIterFunc eFunc )
void ScInterpreter::ScDBSum()
{
+ StackPrinter __stack_printer__("ScInterpreter::ScDBSum");
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScDBSum" );
DBIterator( ifSUM );
}
@@ -5861,13 +5886,12 @@ void ScInterpreter::ScDBSum()
void ScInterpreter::ScDBCount()
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScDBCount" );
- SCTAB nTab;
- ScQueryParam aQueryParam;
+ ::std::auto_ptr<ScQueryParam> pQueryParam(new ScQueryParam);
BOOL bMissingField = TRUE;
- if ( GetDBParams( nTab, aQueryParam, bMissingField) )
+ if ( GetDBParams(*pQueryParam, bMissingField) )
{
ULONG nCount = 0;
- if ( bMissingField )
+ if ( bMissingField && pQueryParam->GetType() == ScQueryParamBase::INTERNAL )
{ // count all matching records
// TODO: currently the QueryIterators only return cell pointers of
// existing cells, so if a query matches an empty cell there's
@@ -5877,7 +5901,8 @@ void ScInterpreter::ScDBCount()
// have to live with it until we reimplement the iterators to also
// return empty cells, which would mean to adapt all callers of
// iterators.
- ScQueryCellIterator aCellIter( pDok, nTab, aQueryParam);
+ SCTAB nTab = pQueryParam->nTab;
+ ScQueryCellIterator aCellIter( pDok, nTab, *pQueryParam);
if ( aCellIter.GetFirst() )
{
do
@@ -5890,7 +5915,7 @@ void ScInterpreter::ScDBCount()
{ // count only matching records with a value in the "result" field
double nVal;
USHORT nErr = 0;
- ScQueryValueIterator aValIter( pDok, nTab, aQueryParam);
+ ScQueryValueIterator aValIter( pDok, pQueryParam.release());
if ( aValIter.GetFirst( nVal, nErr) && !nErr )
{
do
@@ -5910,11 +5935,11 @@ void ScInterpreter::ScDBCount()
void ScInterpreter::ScDBCount2()
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScDBCount2" );
- SCTAB nTab;
ScQueryParam aQueryParam;
BOOL bMissingField = TRUE;
- if (GetDBParams( nTab, aQueryParam, bMissingField))
+ if (GetDBParams(aQueryParam, bMissingField))
{
+ SCTAB nTab = aQueryParam.nTab;
ULONG nCount = 0;
ScQueryCellIterator aCellIter(pDok, nTab, aQueryParam);
if ( aCellIter.GetFirst() )
@@ -5968,14 +5993,13 @@ void ScInterpreter::GetDBStVarParams( double& rVal, double& rValCount )
rValCount = 0.0;
double fSum = 0.0;
- SCTAB nTab;
- ScQueryParam aQueryParam;
+ ::std::auto_ptr<ScQueryParam> pQueryParam(new ScQueryParam);
BOOL bMissingField = FALSE;
- if (GetDBParams( nTab, aQueryParam, bMissingField))
+ if (GetDBParams(*pQueryParam, bMissingField))
{
double fVal;
USHORT nErr;
- ScQueryValueIterator aValIter(pDok, nTab, aQueryParam);
+ ScQueryValueIterator aValIter(pDok, pQueryParam.release());
if (aValIter.GetFirst(fVal, nErr) && !nErr)
{
do
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index cf8dc7e2c..12f8006c2 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -68,6 +68,7 @@
#include "jumpmatrix.hxx"
#include "parclass.hxx"
#include "externalrefmgr.hxx"
+#include "doubleref.hxx"
#include <math.h>
#include <float.h>
@@ -80,6 +81,42 @@ using namespace formula;
#define ADDIN_MAXSTRLEN 256
+#include <stdio.h>
+#include <string>
+#include <sys/time.h>
+
+namespace {
+
+class StackPrinter
+{
+public:
+ explicit StackPrinter(const char* msg) :
+ msMsg(msg)
+ {
+ fprintf(stdout, "%s: --begin\n", msMsg.c_str());
+ mfStartTime = getTime();
+ }
+
+ ~StackPrinter()
+ {
+ double fEndTime = getTime();
+ fprintf(stdout, "%s: --end (duration: %g sec)\n", msMsg.c_str(), (fEndTime-mfStartTime));
+ }
+
+private:
+ double getTime() const
+ {
+ timeval tv;
+ gettimeofday(&tv, NULL);
+ return tv.tv_sec + tv.tv_usec / 1000000.0;
+ }
+
+ ::std::string msMsg;
+ double mfStartTime;
+};
+
+}
+
// Implementiert in ui\miscdlgs\teamdlg.cxx
extern void ShowTheTeam();
@@ -1021,6 +1058,46 @@ void ScInterpreter::DoubleRefToVars( const ScToken* p,
}
}
+ScDoubleRefBase* ScInterpreter::PopDoubleRef()
+{
+ if (!sp)
+ {
+ SetError(errUnknownStackVariable);
+ return NULL;
+ }
+
+ --sp;
+ FormulaToken* p = pStack[sp];
+ switch (p->GetType())
+ {
+ case svError:
+ fprintf(stdout, "ScInterpreter::PopDoubleRef: error\n");
+ nGlobalError = p->GetError();
+ break;
+ case svDoubleRef:
+ {
+ fprintf(stdout, "ScInterpreter::PopDoubleRef: double ref\n");
+ SCCOL nCol1, nCol2;
+ SCROW nRow1, nRow2;
+ SCTAB nTab1, nTab2;
+ DoubleRefToVars(static_cast<ScToken*>(p),
+ nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, false);
+
+ return new ScInternalDoubleRef(pDok,
+ ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
+ }
+ break;
+ case svMatrix:
+ {
+ fprintf(stdout, "ScInterpreter::PopDoubleRef: matrix\n");
+ }
+ break;
+ default:
+ fprintf(stdout, "ScInterpreter::PopDoubleRef: other\n");
+ SetError( errIllegalParameter);
+ }
+ return NULL;
+}
void ScInterpreter::PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
@@ -1034,13 +1111,16 @@ void ScInterpreter::PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
switch (p->GetType())
{
case svError:
+ fprintf(stdout, "ScInterpreter::PopDoubleRef: error\n");
nGlobalError = p->GetError();
break;
case svDoubleRef:
+ fprintf(stdout, "ScInterpreter::PopDoubleRef: double ref\n");
DoubleRefToVars( static_cast<ScToken*>(p), rCol1, rRow1, rTab1, rCol2, rRow2, rTab2,
bDontCheckForTableOp);
break;
default:
+ fprintf(stdout, "ScInterpreter::PopDoubleRef: other\n");
SetError( errIllegalParameter);
}
}
@@ -1860,11 +1940,11 @@ ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix( double& rDouble,
void ScInterpreter::ScDBGet()
{
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScDBGet" );
- SCTAB nTab;
ScQueryParam aQueryParam;
BOOL bMissingField = FALSE;
- if (GetDBParams( nTab, aQueryParam, bMissingField))
+ if (GetDBParams(aQueryParam, bMissingField))
{
+ SCTAB nTab = aQueryParam.nTab;
ScBaseCell* pCell;
ScQueryCellIterator aCellIter(pDok, nTab, aQueryParam);
if ( (pCell = aCellIter.GetFirst()) != NULL )
@@ -2986,6 +3066,7 @@ void ScInterpreter::ScColRowNameAuto()
void ScInterpreter::ScExternalRef()
{
+ StackPrinter __stack_printer__("ScInterpreter::ScExternalRef");
ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
const String* pFile = pRefMgr->getExternalFileName(pCur->GetIndex());
if (!pFile)
@@ -2995,6 +3076,7 @@ void ScInterpreter::ScExternalRef()
{
case svExternalSingleRef:
{
+ fprintf(stdout, "ScInterpreter::ScExternalRef: single ref\n");
ScSingleRefData aData(static_cast<const ScToken*>(pCur)->GetSingleRef());
if (aData.IsTabRel())
{
@@ -3012,6 +3094,7 @@ void ScInterpreter::ScExternalRef()
break;
PushTempToken( *xNew); // push a clone
+ fprintf(stdout, "ScInterpreter::ScExternalRef: token pushed\n");
if (aFmt.mbIsSet)
{
@@ -3023,6 +3106,7 @@ void ScInterpreter::ScExternalRef()
//break; // unreachable, prevent compiler warning
case svExternalDoubleRef:
{
+ fprintf(stdout, "ScInterpreter::ScExternalRef: double ref\n");
ScComplexRefData aData(static_cast<const ScToken*>(pCur)->GetDoubleRef());
if (aData.Ref1.IsTabRel() || aData.Ref2.IsTabRel())
{
@@ -3051,6 +3135,7 @@ void ScInterpreter::ScExternalRef()
}
PushMatrix(p->GetMatrix());
+ fprintf(stdout, "ScInterpreter::ScExternalRef: matrix pushed\n");
return;
}
//break; // unreachable, prevent compiler warning
diff --git a/sc/source/core/tool/makefile.mk b/sc/source/core/tool/makefile.mk
index ac0aa23fc..e8a2e0fb7 100644
--- a/sc/source/core/tool/makefile.mk
+++ b/sc/source/core/tool/makefile.mk
@@ -76,6 +76,7 @@ SLOFILES = \
$(SLO)$/detdata.obj \
$(SLO)$/detfunc.obj \
$(SLO)$/docoptio.obj \
+ $(SLO)$/doubleref.obj \
$(SLO)$/editutil.obj \
$(SLO)$/filtopt.obj \
$(SLO)$/formulaparserpool.obj \
@@ -96,6 +97,7 @@ SLOFILES = \
$(SLO)$/printopt.obj \
$(SLO)$/prnsave.obj \
$(SLO)$/progress.obj \
+ $(SLO)$/queryparam.obj \
$(SLO)$/rangelst.obj \
$(SLO)$/rangenam.obj \
$(SLO)$/rangeseq.obj \
@@ -123,6 +125,7 @@ EXCEPTIONSFILES= \
$(SLO)$/chartlock.obj \
$(SLO)$/chgtrack.obj \
$(SLO)$/compiler.obj \
+ $(SLO)$/doubleref.obj \
$(SLO)$/formulaparserpool.obj \
$(SLO)$/interpr1.obj \
$(SLO)$/interpr2.obj \
@@ -131,6 +134,7 @@ EXCEPTIONSFILES= \
$(SLO)$/interpr5.obj \
$(SLO)$/lookupcache.obj \
$(SLO)$/prnsave.obj \
+ $(SLO)$/queryparam.obj \
$(SLO)$/reftokenhelper.obj \
$(SLO)$/token.obj
diff --git a/sc/source/core/tool/queryparam.cxx b/sc/source/core/tool/queryparam.cxx
new file mode 100644
index 000000000..089e707a8
--- /dev/null
+++ b/sc/source/core/tool/queryparam.cxx
@@ -0,0 +1,296 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: interpr4.cxx,v $
+ * $Revision: 1.57.92.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+// INCLUDE ---------------------------------------------------------------
+
+#include "queryparam.hxx"
+
+// ============================================================================
+
+ScQueryParamBase::ScQueryParamBase(DataType eType) :
+ nEntryCount(0), meType(eType)
+{
+}
+
+ScQueryParamBase::ScQueryParamBase(const ScQueryParamBase& r) :
+ bHasHeader(r.bHasHeader), bByRow(r.bByRow), bInplace(r.bInplace), bCaseSens(r.bCaseSens),
+ bRegExp(r.bRegExp), bDuplicate(r.bDuplicate),
+ meType(r.meType)
+{
+}
+
+ScQueryParamBase::~ScQueryParamBase()
+{
+ delete[] pEntries;
+}
+
+void ScQueryParamBase::Resize(SCSIZE nNew)
+{
+ if ( nNew < MAXQUERY )
+ nNew = MAXQUERY; // nie weniger als MAXQUERY
+
+ ScQueryEntry* pNewEntries = NULL;
+ if ( nNew )
+ pNewEntries = new ScQueryEntry[nNew];
+
+ SCSIZE nCopy = Min( nEntryCount, nNew );
+ for (SCSIZE i=0; i<nCopy; i++)
+ pNewEntries[i] = pEntries[i];
+
+ if ( nEntryCount )
+ delete[] pEntries;
+ nEntryCount = nNew;
+ pEntries = pNewEntries;
+}
+
+void ScQueryParamBase::DeleteQuery( SCSIZE nPos )
+{
+ if (nPos<nEntryCount)
+ {
+ for (SCSIZE i=nPos; i+1<nEntryCount; i++)
+ pEntries[i] = pEntries[i+1];
+
+ pEntries[nEntryCount-1].Clear();
+ }
+ else
+ {
+ DBG_ERROR("Falscher Parameter bei ScQueryParam2::DeleteQuery");
+ }
+}
+
+void ScQueryParamBase::FillInExcelSyntax(String& aCellStr, SCSIZE nIndex)
+{
+ if (aCellStr.Len() > 0)
+ {
+ if ( nIndex >= nEntryCount )
+ Resize( nIndex+1 );
+
+ ScQueryEntry& rEntry = pEntries[nIndex];
+
+ rEntry.bDoQuery = TRUE;
+ // Operatoren herausfiltern
+ if (aCellStr.GetChar(0) == '<')
+ {
+ if (aCellStr.GetChar(1) == '>')
+ {
+ *rEntry.pStr = aCellStr.Copy(2);
+ rEntry.eOp = SC_NOT_EQUAL;
+ }
+ else if (aCellStr.GetChar(1) == '=')
+ {
+ *rEntry.pStr = aCellStr.Copy(2);
+ rEntry.eOp = SC_LESS_EQUAL;
+ }
+ else
+ {
+ *rEntry.pStr = aCellStr.Copy(1);
+ rEntry.eOp = SC_LESS;
+ }
+ }
+ else if (aCellStr.GetChar(0) == '>')
+ {
+ if (aCellStr.GetChar(1) == '=')
+ {
+ *rEntry.pStr = aCellStr.Copy(2);
+ rEntry.eOp = SC_GREATER_EQUAL;
+ }
+ else
+ {
+ *rEntry.pStr = aCellStr.Copy(1);
+ rEntry.eOp = SC_GREATER;
+ }
+ }
+ else
+ {
+ if (aCellStr.GetChar(0) == '=')
+ *rEntry.pStr = aCellStr.Copy(1);
+ else
+ *rEntry.pStr = aCellStr;
+ rEntry.eOp = SC_EQUAL;
+ }
+ }
+}
+
+ScQueryParamBase::DataType ScQueryParamBase::GetType() const
+{
+ return meType;
+}
+
+// ============================================================================
+
+ScQueryParam::ScQueryParam() :
+ ScQueryParamBase(ScQueryParamBase::INTERNAL)
+{
+ Clear();
+}
+
+//------------------------------------------------------------------------
+
+ScQueryParam::ScQueryParam( const ScQueryParam& r ) :
+ ScQueryParamBase(r),
+ nCol1(r.nCol1),nRow1(r.nRow1),nCol2(r.nCol2),nRow2(r.nRow2),nTab(r.nTab),
+ bMixedComparison(r.bMixedComparison), bDestPers(r.bDestPers),
+ nDestTab(r.nDestTab), nDestCol(r.nDestCol), nDestRow(r.nDestRow)
+{
+ nEntryCount = 0;
+
+ Resize( r.nEntryCount );
+ for (USHORT i=0; i<nEntryCount; i++)
+ pEntries[i] = r.pEntries[i];
+}
+
+//------------------------------------------------------------------------
+
+ScQueryParam::~ScQueryParam()
+{
+}
+
+//------------------------------------------------------------------------
+
+void ScQueryParam::Clear()
+{
+ nCol1=nCol2=nDestCol = 0;
+ nRow1=nRow2=nDestRow = 0;
+ nDestTab = 0;
+ nTab = SCTAB_MAX;
+ bHasHeader = bCaseSens = bRegExp = bMixedComparison = FALSE;
+ bInplace = bByRow = bDuplicate = bDestPers = TRUE;
+
+ Resize( MAXQUERY );
+ for (USHORT i=0; i<MAXQUERY; i++)
+ pEntries[i].Clear();
+}
+
+//------------------------------------------------------------------------
+
+ScQueryParam& ScQueryParam::operator=( const ScQueryParam& r )
+{
+ nCol1 = r.nCol1;
+ nRow1 = r.nRow1;
+ nCol2 = r.nCol2;
+ nRow2 = r.nRow2;
+ nTab = r.nTab;
+ nDestTab = r.nDestTab;
+ nDestCol = r.nDestCol;
+ nDestRow = r.nDestRow;
+ bHasHeader = r.bHasHeader;
+ bInplace = r.bInplace;
+ bCaseSens = r.bCaseSens;
+ bRegExp = r.bRegExp;
+ bMixedComparison = r.bMixedComparison;
+ bDuplicate = r.bDuplicate;
+ bByRow = r.bByRow;
+ bDestPers = r.bDestPers;
+
+ Resize( r.nEntryCount );
+ for (USHORT i=0; i<nEntryCount; i++)
+ pEntries[i] = r.pEntries[i];
+
+ return *this;
+}
+
+//------------------------------------------------------------------------
+
+BOOL ScQueryParam::operator==( const ScQueryParam& rOther ) const
+{
+ BOOL bEqual = FALSE;
+
+ // Anzahl der Queries gleich?
+ USHORT nUsed = 0;
+ USHORT nOtherUsed = 0;
+ while ( nUsed<nEntryCount && pEntries[nUsed].bDoQuery ) ++nUsed;
+ while ( nOtherUsed<rOther.nEntryCount && rOther.pEntries[nOtherUsed].bDoQuery )
+ ++nOtherUsed;
+
+ if ( (nUsed == nOtherUsed)
+ && (nCol1 == rOther.nCol1)
+ && (nRow1 == rOther.nRow1)
+ && (nCol2 == rOther.nCol2)
+ && (nRow2 == rOther.nRow2)
+ && (nTab == rOther.nTab)
+ && (bHasHeader == rOther.bHasHeader)
+ && (bByRow == rOther.bByRow)
+ && (bInplace == rOther.bInplace)
+ && (bCaseSens == rOther.bCaseSens)
+ && (bRegExp == rOther.bRegExp)
+ && (bMixedComparison == rOther.bMixedComparison)
+ && (bDuplicate == rOther.bDuplicate)
+ && (bDestPers == rOther.bDestPers)
+ && (nDestTab == rOther.nDestTab)
+ && (nDestCol == rOther.nDestCol)
+ && (nDestRow == rOther.nDestRow) )
+ {
+ bEqual = TRUE;
+ for ( USHORT i=0; i<nUsed && bEqual; i++ )
+ bEqual = pEntries[i] == rOther.pEntries[i];
+ }
+ return bEqual;
+}
+
+//------------------------------------------------------------------------
+
+void ScQueryParam::MoveToDest()
+{
+ if (!bInplace)
+ {
+ SCsCOL nDifX = ((SCsCOL) nDestCol) - ((SCsCOL) nCol1);
+ SCsROW nDifY = ((SCsROW) nDestRow) - ((SCsROW) nRow1);
+ SCsTAB nDifZ = ((SCsTAB) nDestTab) - ((SCsTAB) nTab);
+
+ nCol1 = sal::static_int_cast<SCCOL>( nCol1 + nDifX );
+ nRow1 = sal::static_int_cast<SCROW>( nRow1 + nDifY );
+ nCol2 = sal::static_int_cast<SCCOL>( nCol2 + nDifX );
+ nRow2 = sal::static_int_cast<SCROW>( nRow2 + nDifY );
+ nTab = sal::static_int_cast<SCTAB>( nTab + nDifZ );
+ for (USHORT i=0; i<nEntryCount; i++)
+ pEntries[i].nField += nDifX;
+
+ bInplace = TRUE;
+ }
+ else
+ {
+ DBG_ERROR("MoveToDest, bInplace == TRUE");
+ }
+}
+
+// ============================================================================
+
+ScQueryParamMatrix::ScQueryParamMatrix() :
+ ScQueryParamBase(ScQueryParamBase::MATRIX)
+{
+}
+
+ScQueryParamMatrix::~ScQueryParamMatrix()
+{
+}
+