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 <lio...@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 <lio...@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
_______________________________________________ LibreOffice mailing list LibreOffice@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice