Kaydet (Commit) 44dcb37b authored tarafından Kohei Yoshida's avatar Kohei Yoshida

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
üst 585b3ebe
......@@ -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;
......
......@@ -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;
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment