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
- [PATCH] [REVIEW:3-5] fdo#46163 database form listbox only for VARCHAR · Lionel Elie Mamane
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.