Date: prev next · Thread: first prev next last
2012 Archives by date, by thread · List index


Just reported and fixed fdo#46163. A list box is a control that is
supposed to match two sets of data:

 An entry in the "list content" property is matched to the
 corresponding entry in the "list entries" property (yeah, that's
 rather confusing naming...). The "list entries" entry is shown to the
 user, but the "list content" entry is stored in the database.

The bug: This matching works only if the column is of type
VARCHAR. Even "CHAR" does not work, and in particular integer types do
not work; integer types are a common case: store a reference number in
the database, but show the user a nice textual description.

To understand how stupid this sounds to the user, note that VARCHAR is
the type of variable-length strings and CHAR the type of fixed-length
strings, not "a single character" (unless the length is 1, obviously).

Attached patch 0003-fdo-46163-convert-bound-values-to-bound-column-s-typ.patch
makes sure the values are converted to the right type before being
compared to the value in the database.

Attached patch
0001-ORowSetValue-setTypeKind-correctly-convert-to-C-LOB-.patch
avoids a crash under some conditions that can be triggered after
application of other patch: instead of assuming the ORowSetValue
already contains an Any, construct one if necessary. Note that the
other cases already do type conversion "nicely", e.g. string to int or
8-bit int to 32-bit int.


Please apply both to libreoffice-3-5. I haven't tested 3.4 in any way,
if you feel like it (and the affected code looks unchanged), you can
use your own judgement.


-- 
Lionel
From aef29c37fbe2bf2d248048c699972fb9e0ac2b4e Mon Sep 17 00:00:00 2001
From: Lionel Elie Mamane <lionel@mamane.lu>
Date: Thu, 16 Feb 2012 09:06:26 +0100
Subject: [PATCH 1/3] ORowSetValue::setTypeKind: correctly convert to
 (C)LOB/OBJECT/OTHER

as opposed to crashing
---
 connectivity/source/commontools/FValue.cxx |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/connectivity/source/commontools/FValue.cxx b/connectivity/source/commontools/FValue.cxx
index 93a8c9d..acd1ef0 100644
--- a/connectivity/source/commontools/FValue.cxx
+++ b/connectivity/source/commontools/FValue.cxx
@@ -254,11 +254,10 @@ void ORowSetValue::setTypeKind(sal_Int32 _eType)
             case DataType::CLOB:
             case DataType::OBJECT:
             case DataType::OTHER:
-                (*this) = getAny();
+                (*this) = makeAny();
                 break;
             default:
-                (*this) = getAny();
+                (*this) = makeAny();
                 OSL_FAIL("ORowSetValue:operator==(): UNSPUPPORTED TYPE!");
         }
     }
-- 
1.7.7.3

From c55d050400139a270f5b3b620db4845001db017d Mon Sep 17 00:00:00 2001
From: Lionel Elie Mamane <lionel@mamane.lu>
Date: Thu, 16 Feb 2012 13:24:58 +0100
Subject: [PATCH 3/3] fdo#46163 convert bound values to bound column's type

---
 forms/source/component/ListBox.cxx |   70 +++++++++++++++++++++++++++++-------
 forms/source/component/ListBox.hxx |   11 +++++-
 2 files changed, 67 insertions(+), 14 deletions(-)

diff --git a/forms/source/component/ListBox.cxx b/forms/source/component/ListBox.cxx
index 2453ebc..eb8c6c9 100644
--- a/forms/source/component/ListBox.cxx
+++ b/forms/source/component/ListBox.cxx
@@ -326,7 +326,7 @@ namespace frm
             // propagate
             if ( m_eListSourceType == ListSourceType_VALUELIST )
             {
-                m_aBoundValues = m_aListSourceValues;
+                setBoundValues(m_aListSourceValues);
             }
             else
             {
@@ -556,7 +556,7 @@ namespace frm
             OSL_FAIL("OListBoxModel::read : invalid (means unknown) version !");
             ValueList().swap(m_aListSourceValues);
             m_aBoundColumn <<= (sal_Int16)0;
-            ValueList().swap(m_aBoundValues);
+            clearBoundValues();
             m_eListSourceType = ListSourceType_VALUELIST;
             m_aDefaultSelectSeq.realloc(0);
             defaultCommonProperties();
@@ -674,7 +674,7 @@ namespace frm
         // outta here if we don't have all pre-requisites
         if ( !xConnection.is() || sListSource.isEmpty() )
         {
-            ValueList().swap(m_aBoundValues);
+            clearBoundValues();
             return;
         }
 
@@ -924,7 +924,7 @@ namespace frm
             m_nNULLPos = 0;
         }
 
-        m_aBoundValues = aValueList;
+        setBoundValues(aValueList);
 
         setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( lcl_convertToStringSequence( 
aDisplayList ) ) );
     }
@@ -948,7 +948,7 @@ namespace frm
     {
         if ( m_eListSourceType != ListSourceType_VALUELIST )
         {
-            ValueList().swap(m_aBoundValues);
+            clearBoundValues();
             m_nNULLPos = -1;
             m_nBoundColumnType = DataType::SQLNULL;
 
@@ -960,19 +960,63 @@ namespace frm
     }
 
     //------------------------------------------------------------------------------
+    void OListBoxModel::setBoundValues(const ValueList &l)
+    {
+        m_aConvertedBoundValues.clear();
+        m_aBoundValues = l;
+    }
+
+    //------------------------------------------------------------------------------
+    void OListBoxModel::clearBoundValues()
+    {
+        ValueList().swap(m_aConvertedBoundValues);
+        ValueList().swap(m_aBoundValues);
+    }
+
+    //------------------------------------------------------------------------------
+    void OListBoxModel::convertBoundValues(const sal_Int32 nFieldType) const
+    {
+        m_aConvertedBoundValues.resize(m_aBoundValues.size());
+        ValueList::const_iterator src = m_aBoundValues.begin();
+        const ValueList::const_iterator end = m_aBoundValues.end();
+        ValueList::iterator dst = m_aConvertedBoundValues.begin();
+        for (; src != end; ++src, ++dst )
+        {
+            *dst = *src;
+            dst->setTypeKind(nFieldType);
+        }
+        m_nConvertedBoundValuesType = nFieldType;
+        OSL_ENSURE(dst == m_aConvertedBoundValues.end(), "OListBoxModel::convertBoundValues 
expected to have overwritten all of m_aConvertedBoundValues, but did not.");
+    }
+    //------------------------------------------------------------------------------
+    sal_Int32 OListBoxModel::getValueType() const
+    {
+        return impl_hasBoundComponent() ? m_nBoundColumnType : getFieldType();
+    }
+    //------------------------------------------------------------------------------
     ValueList OListBoxModel::impl_getValues() const
     {
+        const sal_Int32 nFieldType = getValueType();
+
+        if ( !m_aConvertedBoundValues.empty() && m_nConvertedBoundValuesType == nFieldType )
+            return m_aConvertedBoundValues;
+
         if ( !m_aBoundValues.empty() )
-            return m_aBoundValues;
+        {
+            convertBoundValues(nFieldType);
+            return m_aConvertedBoundValues;
+        }
 
         Sequence< ::rtl::OUString > aStringItems( getStringItemList() );
         ValueList aValues( aStringItems.getLength() );
-        ::std::copy(
-            aStringItems.getConstArray(),
-            aStringItems.getConstArray() + aStringItems.getLength(),
-            aValues.begin()
-        );
-
+        ValueList::iterator dst = aValues.begin();
+        const ::rtl::OUString *src (aStringItems.getConstArray());
+        const ::rtl::OUString * const end = src + aStringItems.getLength();
+        for (; src < end; ++src, ++dst )
+        {
+            *dst = *src;
+            dst->setTypeKind(nFieldType);
+        }
         return aValues;
     }
     //------------------------------------------------------------------------------
@@ -1045,7 +1089,7 @@ namespace frm
         Sequence< sal_Int16 > aSelectionIndicies;
 
         ORowSetValue aCurrentValue;
-        aCurrentValue.fill( impl_hasBoundComponent() ? m_nBoundColumnType : getFieldType(), 
m_xColumn );
+        aCurrentValue.fill( getValueType(), m_xColumn );
 
         // reset selection for NULL values
         if ( aCurrentValue.isNull() )
diff --git a/forms/source/component/ListBox.hxx b/forms/source/component/ListBox.hxx
index cd1302c..d64a5a8 100644
--- a/forms/source/component/ListBox.hxx
+++ b/forms/source/component/ListBox.hxx
@@ -79,7 +79,9 @@ class OListBoxModel :public OBoundControlModel
     ::com::sun::star::form::ListSourceType      m_eListSourceType;      // type der list source
     ::com::sun::star::uno::Any                  m_aBoundColumn;
     ValueList                                   m_aListSourceValues;
-    ValueList                                   m_aBoundValues;
+    ValueList                                   m_aBoundValues;         // do not write directly; 
use setBoundValues()
+    mutable ValueList                           m_aConvertedBoundValues;
+    mutable sal_Int32                           m_nConvertedBoundValuesType;
     ::com::sun::star::uno::Sequence<sal_Int16>  m_aDefaultSelectSeq;    // DefaultSelected
     // </properties>
 
@@ -181,8 +183,15 @@ private:
     */
     void        impl_refreshDbEntryList( bool _bForce );
 
+    void        setBoundValues(const ValueList&);
+    void        clearBoundValues();
+
     ValueList   impl_getValues() const;
 
+    sal_Int32   getValueType() const;
+
+    void        convertBoundValues(sal_Int32 nType) const;
+
     bool        impl_hasBoundComponent() const { return m_nBoundColumnType != 
::com::sun::star::sdbc::DataType::SQLNULL; }
 };
 
-- 
1.7.7.3


Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.