User: ihi     
Date: 2006/10/18 06:06:18

Modified:
   dba/connectivity/source/commontools/TTableHelper.cxx

Log:
 INTEGRATION: CWS dba205b (1.5.18); FILE MERGED
 2006/09/04 11:04:31 oj 1.5.18.3: RESYNC: (1.5-1.6); FILE MERGED
 2006/08/15 13:45:23 fs 1.5.18.2: lcl_sanitizeColumnDescs: also allow for 
ordinal positions ranging from 0 to <column_count>-1 (MySQL)
 2006/08/09 20:00:56 fs 1.5.18.1: during #b6248060#: respect the 
OrdinalPosition as returned by XDatabaseMetaData::getColumns - don't assume the 
columns are returned in the same order as they appear in the table

File Changes:

Directory: /dba/connectivity/source/commontools/
================================================

File [changed]: TTableHelper.cxx
Url: 
http://dba.openoffice.org/source/browse/dba/connectivity/source/commontools/TTableHelper.cxx?r1=1.7&r2=1.8
Delta lines:  +109 -10
----------------------
--- TTableHelper.cxx    17 Sep 2006 02:01:37 -0000      1.7
+++ TTableHelper.cxx    18 Oct 2006 13:06:16 -0000      1.8
@@ -75,6 +75,9 @@
 #ifndef _CONNECTIVITY_SDBCX_COLLECTION_HXX_
 #include "connectivity/sdbcx/VCollection.hxx"
 #endif
+#ifndef UNOTOOLS_INC_SHAREDUNOCOMPONENT_HXX
+#include <unotools/sharedunocomponent.hxx>
+#endif
 #ifndef CONNECTIVITY_CONNECTION_HXX
 #include "TConnection.hxx"
 #endif
@@ -136,6 +139,86 @@
        m_xConnection   = NULL;
        m_xMetaData             = NULL;
 }
+
+// -------------------------------------------------------------------------
+namespace
+{
+    typedef sal_Int32   OrdinalPosition;
+    struct ColumnDesc
+    {
+        ::rtl::OUString sName;
+        OrdinalPosition nOrdinalPosition;
+
+        ColumnDesc() {}
+        ColumnDesc( const ::rtl::OUString& _rName, OrdinalPosition _nPosition )
+            :sName( _rName )
+            ,nOrdinalPosition( _nPosition )
+        {
+        }
+    };
+
+    /** collects ColumnDesc's from a resultset produced by 
XDatabaseMetaData::getColumns
+    */
+    void lcl_collectColumnDescs_throw( const Reference< XResultSet >& 
_rxResult, ::std::vector< ColumnDesc >& _out_rColumns )
+    {
+        Reference< XRow > xRow( _rxResult, UNO_QUERY_THROW );
+        ::rtl::OUString sName;
+        OrdinalPosition nOrdinalPosition( 0 );
+           while ( _rxResult->next() )
+        {
+            sName = xRow->getString( 4 );           // COLUMN_NAME
+            nOrdinalPosition = xRow->getInt( 17 );  // ORDINAL_POSITION
+            _out_rColumns.push_back( ColumnDesc( sName, nOrdinalPosition ) );
+        }
+    }
+
+    /** checks a given array of ColumnDesc's whether it has reasonable ordinal 
positions. If not,
+        they will be normalized to be the array index.
+    */
+    void lcl_sanitizeColumnDescs( ::std::vector< ColumnDesc >& _rColumns )
+    {
+        if ( _rColumns.empty() )
+            return;
+
+        // collect all used ordinals
+        ::std::set< OrdinalPosition > aUsedOrdinals;
+        for (   ::std::vector< ColumnDesc >::iterator collect = 
_rColumns.begin();
+                collect != _rColumns.end();
+                ++collect
+            )
+            aUsedOrdinals.insert( collect->nOrdinalPosition );
+
+        // we need to have as much different ordinals as we have different 
columns
+        bool bDuplicates = aUsedOrdinals.size() != _rColumns.size();
+        // and it needs to be a continuous range
+        size_t nOrdinalsRange = *aUsedOrdinals.rbegin() - 
*aUsedOrdinals.begin() + 1;
+        bool bGaps = nOrdinalsRange != _rColumns.size();
+
+        // if that's not the case, normalize it
+        if ( bGaps || bDuplicates )
+        {
+            OSL_ENSURE( false, "lcl_sanitizeColumnDescs: database did provide 
invalid ORDINAL_POSITION values!" );
+
+            OrdinalPosition nNormalizedPosition = 1;
+            for (   ::std::vector< ColumnDesc >::iterator normalize = 
_rColumns.begin();
+                    normalize != _rColumns.end();
+                    ++normalize
+                )
+                normalize->nOrdinalPosition = nNormalizedPosition++;
+            return;
+        }
+
+        // what's left is that the range might not be from 1 to <column 
count>, but for instance
+        // 0 to <column count>-1.
+        size_t nOffset = *aUsedOrdinals.begin() - 1;
+        for (   ::std::vector< ColumnDesc >::iterator offset = 
_rColumns.begin();
+                offset != _rColumns.end();
+                ++offset
+            )
+            offset->nOrdinalPosition -= nOffset;
+    }
+}
+
 // -------------------------------------------------------------------------
 void OTableHelper::refreshColumns()
 {
@@ -145,20 +228,36 @@
                Any aCatalog;
                if ( m_CatalogName.getLength() )
                        aCatalog <<= m_CatalogName;
-OSL_TRACE( "meta data: %p", getMetaData().get() );
-               Reference< XResultSet > xResult = getMetaData()->getColumns(
+
+        ::utl::SharedUNOComponent< XResultSet > xResult( 
getMetaData()->getColumns(
             aCatalog,
             m_SchemaName,
             m_Name,
-            ::rtl::OUString::createFromAscii("%"));
+            ::rtl::OUString::createFromAscii("%")
+        ) );
 
-               if ( xResult.is() )
-               {
-                       Reference< XRow > xRow(xResult,UNO_QUERY);
-                       while( xResult->next() )
-                               aVector.push_back(xRow->getString(4));
-                       ::comphelper::disposeComponent(xResult);
-               }
+        // collect the column names, together with their ordinal position
+        ::std::vector< ColumnDesc > aColumns;
+        lcl_collectColumnDescs_throw( xResult, aColumns );
+
+        // ensure that the ordinal positions as obtained from the meta data do 
make sense
+        lcl_sanitizeColumnDescs( aColumns );
+
+        // sort by ordinal position
+        ::std::map< OrdinalPosition, ::rtl::OUString > aSortedColumns;
+        for (   ::std::vector< ColumnDesc >::const_iterator copy = 
aColumns.begin();
+                copy != aColumns.end();
+                ++copy
+            )
+            aSortedColumns[ copy->nOrdinalPosition ] = copy->sName;
+
+        // copy them to aVector, now that we have the proper ordering
+        ::std::transform(
+            aSortedColumns.begin(),
+            aSortedColumns.end(),
+            ::std::insert_iterator< TStringVector >( aVector, aVector.begin() 
),
+            ::std::select2nd< ::std::map< OrdinalPosition, ::rtl::OUString 
>::value_type >()
+        );
        }
 
        if(m_pColumns)




---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to