[Libreoffice-commits] .: sc/inc sc/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Wed Aug 22 20:15:20 PDT 2012


 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.yoshida at 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);
 


More information about the Libreoffice-commits mailing list