summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@gmail.com>2012-08-22 23:10:45 -0400
committerKohei Yoshida <kohei.yoshida@gmail.com>2012-08-22 23:15:18 -0400
commit44dcb37bf9339611559743f35a93dd674227b357 (patch)
tree61486541abd94383342aeacd246a5d1addcaa7a3 /sc
parent585b3ebea4312dbfa86ad9f4a72f0014fe2eacec (diff)
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
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/dpcache.hxx22
-rw-r--r--sc/source/core/data/dpcache.cxx115
-rw-r--r--sc/source/core/data/dpobject.cxx183
3 files changed, 205 insertions, 115 deletions
diff --git a/sc/inc/dpcache.hxx b/sc/inc/dpcache.hxx
index 68b1029edc5d..d68f3482de0c 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 ff8fc6e45494..fa2b1efbaf0f 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 dcef79f5748c..4918b68eced7 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);