sc/inc/dpcache.hxx | 22 +++- sc/source/core/data/dpcache.cxx | 115 +----------------------- sc/source/core/data/dpobject.cxx | 183 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 205 insertions(+), 115 deletions(-)
New commits: commit 44dcb37bf9339611559743f35a93dd674227b357 Author: Kohei Yoshida <kohei.yosh...@gmail.com> Date: Wed Aug 22 23:10:45 2012 -0400 Abstract database connection from pivot cache to hide UNO API. This is the first step toward unit-testing the initialization code from the database source. Change-Id: I1a7882ba443fd71d4210fb2e2caa195fb71dab92 diff --git a/sc/inc/dpcache.hxx b/sc/inc/dpcache.hxx index 68b1029..d68f348 100644 --- a/sc/inc/dpcache.hxx +++ b/sc/inc/dpcache.hxx @@ -43,12 +43,6 @@ #include <vector> #include <set> -namespace com { namespace sun { namespace star { - namespace sdbc { - class XRowSet; - } -}}} - struct ScQueryParam; class ScDPObject; class ScDPItemData; @@ -102,6 +96,20 @@ public: Field(); }; + /** + * Interface for connecting to database source. Column index is 0-based. + */ + class DBConnector + { + public: + virtual long getColumnCount() const = 0; + virtual rtl::OUString getColumnLabel(long nCol) const = 0; + virtual bool first() = 0; + virtual bool next() = 0; + virtual void finish() = 0; + virtual void getValue(long nCol, ScDPItemData& rData, short& rNumType) const = 0; + }; + private: ScDocument* mpDoc; @@ -148,7 +156,7 @@ public: const ItemsType& GetDimMemberValues( SCCOL nDim ) const; bool InitFromDoc(ScDocument* pDoc, const ScRange& rRange); - bool InitFromDataBase(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XRowSet>& xRowSet, const Date& rNullDate); + bool InitFromDataBase(DBConnector& rDB); SCROW GetRowCount() const; SCROW GetItemDataId( sal_uInt16 nDim, SCROW nRow, bool bRepeatIfEmpty ) const; diff --git a/sc/source/core/data/dpcache.cxx b/sc/source/core/data/dpcache.cxx index ff8fc6e..fa2b1ef 100644 --- a/sc/source/core/data/dpcache.cxx +++ b/sc/source/core/data/dpcache.cxx @@ -45,16 +45,8 @@ #include <unotools/localedatawrapper.hxx> #include <svl/zforlist.hxx> -#include <com/sun/star/sdbc/DataType.hpp> -#include <com/sun/star/sdbc/XResultSetMetaData.hpp> -#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> -#include <com/sun/star/sdbc/XRow.hpp> -#include <com/sun/star/sdbc/XRowSet.hpp> - #include <memory> -const double D_TIMEFACTOR = 86400.0; - using namespace ::com::sun::star; using ::com::sun::star::uno::Exception; @@ -165,85 +157,6 @@ void initFromCell( rData.SetEmpty(); } -void getItemValue( - ScDPCache& rCache, ScDPItemData& rData, const Reference<sdbc::XRow>& xRow, sal_Int32 nType, - long nCol, const Date& rNullDate, short& rNumType) -{ - rNumType = NUMBERFORMAT_NUMBER; - try - { - double fValue = 0.0; - switch (nType) - { - case sdbc::DataType::BIT: - case sdbc::DataType::BOOLEAN: - { - rNumType = NUMBERFORMAT_LOGICAL; - fValue = xRow->getBoolean(nCol) ? 1 : 0; - rData.SetValue(fValue); - break; - } - case sdbc::DataType::TINYINT: - case sdbc::DataType::SMALLINT: - case sdbc::DataType::INTEGER: - case sdbc::DataType::BIGINT: - case sdbc::DataType::FLOAT: - case sdbc::DataType::REAL: - case sdbc::DataType::DOUBLE: - case sdbc::DataType::NUMERIC: - case sdbc::DataType::DECIMAL: - { - //! do the conversion here? - fValue = xRow->getDouble(nCol); - rData.SetValue(fValue); - break; - } - case sdbc::DataType::DATE: - { - rNumType = NUMBERFORMAT_DATE; - - util::Date aDate = xRow->getDate(nCol); - fValue = Date(aDate.Day, aDate.Month, aDate.Year) - rNullDate; - rData.SetValue(fValue); - break; - } - case sdbc::DataType::TIME: - { - rNumType = NUMBERFORMAT_TIME; - - util::Time aTime = xRow->getTime(nCol); - fValue = ( aTime.Hours * 3600 + aTime.Minutes * 60 + - aTime.Seconds + aTime.HundredthSeconds / 100.0 ) / D_TIMEFACTOR; - rData.SetValue(fValue); - break; - } - case sdbc::DataType::TIMESTAMP: - { - rNumType = NUMBERFORMAT_DATETIME; - - util::DateTime aStamp = xRow->getTimestamp(nCol); - fValue = ( Date( aStamp.Day, aStamp.Month, aStamp.Year ) - rNullDate ) + - ( aStamp.Hours * 3600 + aStamp.Minutes * 60 + - aStamp.Seconds + aStamp.HundredthSeconds / 100.0 ) / D_TIMEFACTOR; - rData.SetValue(fValue); - break; - } - case sdbc::DataType::CHAR: - case sdbc::DataType::VARCHAR: - case sdbc::DataType::LONGVARCHAR: - case sdbc::DataType::SQLNULL: - case sdbc::DataType::BINARY: - case sdbc::DataType::VARBINARY: - case sdbc::DataType::LONGVARBINARY: - default: - rData.SetString(rCache.InternString(xRow->getString(nCol))); - } - } - catch (uno::Exception&) - { - } -} - struct Bucket { ScDPItemData maValue; @@ -424,21 +337,13 @@ bool ScDPCache::InitFromDoc(ScDocument* pDoc, const ScRange& rRange) return true; } -bool ScDPCache::InitFromDataBase (const Reference<sdbc::XRowSet>& xRowSet, const Date& rNullDate) +bool ScDPCache::InitFromDataBase(DBConnector& rDB) { Clear(); - if (!xRowSet.is()) - // Don't even waste time to go any further. - return false; try { - Reference<sdbc::XResultSetMetaDataSupplier> xMetaSupp(xRowSet, UNO_QUERY_THROW); - Reference<sdbc::XResultSetMetaData> xMeta = xMetaSupp->getMetaData(); - if (!xMeta.is()) - return false; - - mnColumnCount = xMeta->getColumnCount(); + mnColumnCount = rDB.getColumnCount(); maFields.clear(); maFields.reserve(mnColumnCount); for (size_t i = 0; i < static_cast<size_t>(mnColumnCount); ++i) @@ -452,19 +357,17 @@ bool ScDPCache::InitFromDataBase (const Reference<sdbc::XRowSet>& xRowSet, const for (sal_Int32 nCol = 0; nCol < mnColumnCount; ++nCol) { - rtl::OUString aColTitle = xMeta->getColumnLabel(nCol+1); - aColTypes[nCol] = xMeta->getColumnType(nCol+1); + rtl::OUString aColTitle = rDB.getColumnLabel(nCol); AddLabel(aColTitle); } - // Now get the data rows. - Reference<sdbc::XRow> xRow(xRowSet, UNO_QUERY_THROW); - std::vector<Bucket> aBuckets; ScDPItemData aData; for (sal_Int32 nCol = 0; nCol < mnColumnCount; ++nCol) { - xRowSet->first(); + if (!rDB.first()) + continue; + aBuckets.clear(); Field& rField = maFields[nCol]; SCROW nRow = 0; @@ -472,7 +375,7 @@ bool ScDPCache::InitFromDataBase (const Reference<sdbc::XRowSet>& xRowSet, const { short nFormatType = NUMBERFORMAT_UNDEFINED; aData.SetEmpty(); - getItemValue(*this, aData, xRow, aColTypes[nCol], nCol+1, rNullDate, nFormatType); + rDB.getValue(nCol, aData, nFormatType); aBuckets.push_back(Bucket(aData, 0, nRow)); if (!aData.IsEmpty()) { @@ -483,12 +386,12 @@ bool ScDPCache::InitFromDataBase (const Reference<sdbc::XRowSet>& xRowSet, const ++nRow; } - while (xRowSet->next()); + while (rDB.next()); processBuckets(aBuckets, rField); } - xRowSet->beforeFirst(); + rDB.finish(); PostInit(); return true; diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx index dcef79f..4918b68 100644 --- a/sc/source/core/data/dpobject.cxx +++ b/sc/source/core/data/dpobject.cxx @@ -53,6 +53,10 @@ #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/sdb/XCompletedExecution.hpp> +#include <com/sun/star/sdbc/DataType.hpp> +#include <com/sun/star/sdbc/XResultSetMetaData.hpp> +#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#include <com/sun/star/sdbc/XRow.hpp> #include <com/sun/star/sdbc/XRowSet.hpp> #include <com/sun/star/sheet/GeneralFunction.hpp> #include <com/sun/star/sheet/DataPilotFieldFilter.hpp> @@ -108,6 +112,165 @@ using ::rtl::OUString; #define SCDPSOURCE_SERVICE "com.sun.star.sheet.DataPilotSource" +namespace { + +const double D_TIMEFACTOR = 86400.0; + +/** + * Database connection implementation for UNO database API. Note that in + * the UNO database API, column index is 1-based, whereas the interface + * requires that column index be 0-based. + */ +class DBConnector : public ScDPCache::DBConnector +{ + ScDPCache& mrCache; + + uno::Reference<sdbc::XRowSet> mxRowSet; + uno::Reference<sdbc::XRow> mxRow; + uno::Reference<sdbc::XResultSetMetaData> mxMetaData; + Date maNullDate; + +public: + DBConnector(ScDPCache& rCache, const uno::Reference<sdbc::XRowSet>& xRowSet, const Date& rNullDate); + ~DBConnector(); + + bool isValid() const; + + virtual void getValue(long nCol, ScDPItemData &rData, short& rNumType) const; + virtual OUString getColumnLabel(long nCol) const; + virtual long getColumnCount() const; + virtual bool first(); + virtual bool next(); + virtual void finish(); +}; + +DBConnector::DBConnector(ScDPCache& rCache, const uno::Reference<sdbc::XRowSet>& xRowSet, const Date& rNullDate) : + mrCache(rCache), mxRowSet(xRowSet), maNullDate(rNullDate) +{ + Reference<sdbc::XResultSetMetaDataSupplier> xMetaSupp(mxRowSet, UNO_QUERY); + if (xMetaSupp.is()) + mxMetaData = xMetaSupp->getMetaData(); + + mxRow.set(mxRowSet, UNO_QUERY); +} + +DBConnector::~DBConnector() +{ +} + +bool DBConnector::isValid() const +{ + return mxRowSet.is() && mxRow.is() && mxMetaData.is(); +} + +bool DBConnector::first() +{ + return mxRowSet->first(); +} + +bool DBConnector::next() +{ + return mxRowSet->next(); +} + +void DBConnector::finish() +{ + if (mxRowSet.is()) + mxRowSet->beforeFirst(); +} + +long DBConnector::getColumnCount() const +{ + return mxMetaData->getColumnCount(); +} + +OUString DBConnector::getColumnLabel(long nCol) const +{ + return mxMetaData->getColumnLabel(nCol+1); +} + +void DBConnector::getValue(long nCol, ScDPItemData &rData, short& rNumType) const +{ + rNumType = NUMBERFORMAT_NUMBER; + sal_Int32 nType = mxMetaData->getColumnType(nCol+1); + + try + { + double fValue = 0.0; + switch (nType) + { + case sdbc::DataType::BIT: + case sdbc::DataType::BOOLEAN: + { + rNumType = NUMBERFORMAT_LOGICAL; + fValue = mxRow->getBoolean(nCol+1) ? 1 : 0; + rData.SetValue(fValue); + break; + } + case sdbc::DataType::TINYINT: + case sdbc::DataType::SMALLINT: + case sdbc::DataType::INTEGER: + case sdbc::DataType::BIGINT: + case sdbc::DataType::FLOAT: + case sdbc::DataType::REAL: + case sdbc::DataType::DOUBLE: + case sdbc::DataType::NUMERIC: + case sdbc::DataType::DECIMAL: + { + //! do the conversion here? + fValue = mxRow->getDouble(nCol+1); + rData.SetValue(fValue); + break; + } + case sdbc::DataType::DATE: + { + rNumType = NUMBERFORMAT_DATE; + + util::Date aDate = mxRow->getDate(nCol+1); + fValue = Date(aDate.Day, aDate.Month, aDate.Year) - maNullDate; + rData.SetValue(fValue); + break; + } + case sdbc::DataType::TIME: + { + rNumType = NUMBERFORMAT_TIME; + + util::Time aTime = mxRow->getTime(nCol+1); + fValue = ( aTime.Hours * 3600 + aTime.Minutes * 60 + + aTime.Seconds + aTime.HundredthSeconds / 100.0 ) / D_TIMEFACTOR; + rData.SetValue(fValue); + break; + } + case sdbc::DataType::TIMESTAMP: + { + rNumType = NUMBERFORMAT_DATETIME; + + util::DateTime aStamp = mxRow->getTimestamp(nCol+1); + fValue = ( Date( aStamp.Day, aStamp.Month, aStamp.Year ) - maNullDate ) + + ( aStamp.Hours * 3600 + aStamp.Minutes * 60 + + aStamp.Seconds + aStamp.HundredthSeconds / 100.0 ) / D_TIMEFACTOR; + rData.SetValue(fValue); + break; + } + case sdbc::DataType::CHAR: + case sdbc::DataType::VARCHAR: + case sdbc::DataType::LONGVARCHAR: + case sdbc::DataType::SQLNULL: + case sdbc::DataType::BINARY: + case sdbc::DataType::VARBINARY: + case sdbc::DataType::LONGVARBINARY: + default: + rData.SetString(mrCache.InternString(mxRow->getString(nCol+1))); + } + } + catch (uno::Exception&) + { + rData.SetEmpty(); + } +} + +} + sal_uInt16 lcl_GetDataGetOrientation( const uno::Reference<sheet::XDimensionsSupplier>& xSource ) { long nRet = sheet::DataPilotFieldOrientation_HIDDEN; @@ -2830,7 +2993,17 @@ const ScDPCache* ScDPCollection::DBCaches::getCache( ::std::auto_ptr<ScDPCache> pCache(new ScDPCache(mpDoc)); SAL_WNODEPRECATED_DECLARATIONS_POP SvNumberFormatter aFormat(mpDoc->GetServiceManager(), ScGlobal::eLnge); - pCache->InitFromDataBase(xRowSet, *aFormat.GetNullDate()); + DBConnector aDB(*pCache, xRowSet, *aFormat.GetNullDate()); + if (!aDB.isValid()) + return NULL; + + if (!pCache->InitFromDataBase(aDB)) + { + // initialization failed. + comphelper::disposeComponent(xRowSet); + return NULL; + } + if (pDimData) pDimData->WriteToCache(*pCache); @@ -2935,12 +3108,18 @@ void ScDPCollection::DBCaches::updateCache( } SvNumberFormatter aFormat(mpDoc->GetServiceManager(), ScGlobal::eLnge); - if (!rCache.InitFromDataBase(xRowSet, *aFormat.GetNullDate())) + DBConnector aDB(rCache, xRowSet, *aFormat.GetNullDate()); + if (!aDB.isValid()) + return; + + if (!rCache.InitFromDataBase(aDB)) { // initialization failed. rRefs.clear(); + comphelper::disposeComponent(xRowSet); return; } + if (pDimData) pDimData->WriteToCache(rCache); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits