forms/source/component/DatabaseForm.cxx |  114 +++++++++++++++++++++++++-------
 forms/source/component/DatabaseForm.hxx |    4 +
 2 files changed, 96 insertions(+), 22 deletions(-)

New commits:
commit e6f843c1c5c2cb075ff0ae358735c5801e56f51f
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sun Jul 20 23:34:03 2025 +0500
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Sun Aug 10 11:16:45 2025 +0200

    tdf#167591: Convert date string to date early
    
    To insert a default value, ODatabaseForm gets its value from column
    properties, and passes to XColumnUpdate. The problem appeared when
    the default was a localized date string, like "20/07/25".
    
    The string was set as the value of a ORowSetValue; then, when its
    value was requested, its getDate() called DBTypeConversion::toDate,
    which only handles ISO date strings. But for correct conversion, not
    only the string is needed, but also its format key. This information
    is already lost at that point. The conversion failed, and the result
    date was invalid, somewhere in the beginning of CE.
    
    Try to overcome this problem by converting the default value from
    date string to date(time) where all the information is available.
    
    Change-Id: I73e96e433895da18cbf6145ffc26b16fa4844452
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188093
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Tested-by: Jenkins
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188682

diff --git a/forms/source/component/DatabaseForm.cxx 
b/forms/source/component/DatabaseForm.cxx
index e45842e02764..bb5cf9200284 100644
--- a/forms/source/component/DatabaseForm.cxx
+++ b/forms/source/component/DatabaseForm.cxx
@@ -53,11 +53,13 @@
 #include <com/sun/star/sdbc/XRowSet.hpp>
 #include <com/sun/star/sdbcx/Privilege.hpp>
 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
+#include <com/sun/star/util/NumberFormatter.hpp>
 #include <com/sun/star/util/URLTransformer.hpp>
 #include <com/sun/star/util/XURLTransformer.hpp>
 #include <com/sun/star/util/XModifiable2.hpp>
 
 #include <comphelper/basicio.hxx>
+#include <comphelper/numbers.hxx>
 #include <comphelper/property.hxx>
 #include <comphelper/seqstream.hxx>
 #include <comphelper/sequence.hxx>
@@ -68,6 +70,7 @@
 #include <rtl/math.hxx>
 #include <rtl/tencinfo.h>
 #include <svl/inettype.hxx>
+#include <svl/numformat.hxx>
 #include <tools/datetime.hxx>
 #include <tools/debug.hxx>
 #include <comphelper/diagnose_ex.hxx>
@@ -1923,6 +1926,70 @@ void SAL_CALL ODatabaseForm::reset()
     }
 }
 
+Reference<XNumberFormatter> ODatabaseForm::getFormatter()
+{
+    if (auto xSupplier = dbtools::getNumberFormats(getConnection(), true, 
m_xContext))
+    {
+        auto result = NumberFormatter::create(m_xContext);
+        result->attachNumberFormatsSupplier(xSupplier);
+        return result;
+    }
+    return {};
+}
+
+static void maybeConvertDefaultStringToDate(Any& def, const auto& 
getFieldPropOrDefault,
+                                            const auto& getFormatter)
+{
+    OUString sDefault;
+    if (!(def >>= sDefault))
+        return;
+
+    sal_Int32 dataType = getFieldPropOrDefault(PROPERTY_FIELDTYPE, 
sal_Int32());
+    if (dataType != css::sdbc::DataType::DATE && dataType != 
css::sdbc::DataType::TIMESTAMP)
+        return;
+
+    Reference<XNumberFormatter> xFormatter = getFormatter();
+    if (!xFormatter)
+        return;
+
+    // Convert to a date
+    sal_uInt32 nFormatKey = xFormatter->detectNumberFormat(
+        getFieldPropOrDefault(PROPERTY_FORMATKEY, sal_uInt32()), sDefault);
+    sal_Int16 nType = comphelper::getNumberFormatType(xFormatter, nFormatKey);
+    if ((nType & css::util::NumberFormat::DATE) == 0)
+        return;
+
+    Reference<XNumberFormatsSupplier> xSupplier = 
xFormatter->getNumberFormatsSupplier();
+    css::util::Date aNull;
+    try
+    {
+        if 
(!(xSupplier->getNumberFormatSettings()->getPropertyValue(u"NullDate"_ustr) >>= 
aNull))
+            return;
+    }
+    catch (const Exception&)
+    {
+        return;
+    }
+    ::Date d(aNull);
+
+    double value = xFormatter->convertStringToNumber(nFormatKey, sDefault);
+    switch (dataType)
+    {
+        case css::sdbc::DataType::DATE:
+        {
+            d.AddDays(value);
+            def <<= d.GetUNODate();
+            break;
+        }
+        case css::sdbc::DataType::TIMESTAMP:
+        {
+            ::DateTime dt(d);
+            dt.AddTime(value);
+            def <<= dt.GetUNODateTime();
+            break;
+        }
+    }
+}
 
 void ODatabaseForm::reset_impl(bool _bApproveByListeners)
 {
@@ -1956,24 +2023,27 @@ void ODatabaseForm::reset_impl(bool 
_bApproveByListeners)
                 if ( !xColUpdate.is() )
                     continue;
 
-                Reference< XPropertySetInfo > xPSI;
-                if ( xColProps.is() )
-                    xPSI = xColProps->getPropertySetInfo( );
-
-                static constexpr OUString PROPERTY_CONTROLDEFAULT = 
u"ControlDefault"_ustr;
-                if (!xPSI || !xPSI->hasPropertyByName(PROPERTY_CONTROLDEFAULT))
-                    continue;
+                auto getPropValOrDefault = [&xColProps, xPSI = 
xColProps->getPropertySetInfo()](
+                                               const OUString& propname, auto 
default_value)
+                {
+                    if (xPSI && xPSI->hasPropertyByName(propname))
+                        fromAny(xColProps->getPropertyValue(propname), 
&default_value);
+                    return default_value;
+                };
 
-                Any aDefault = xColProps->getPropertyValue( 
PROPERTY_CONTROLDEFAULT );
+                Any aDefault = getPropValOrDefault(u"ControlDefault"_ustr, 
Any());
                 if (!aDefault.hasValue())
                     continue;
 
-                bool bReadOnly = false;
-                if ( xPSI->hasPropertyByName( PROPERTY_ISREADONLY ) )
-                    xColProps->getPropertyValue( PROPERTY_ISREADONLY ) >>= 
bReadOnly;
-                if (bReadOnly)
+                if (getPropValOrDefault(PROPERTY_ISREADONLY, false))
                     continue;
 
+                // If the column is a date, and the default is a string, it 
may be
+                // impossible to convert the string to date at a later stage 
(namely, in
+                // DBTypeConversion::getValue, where the column formatting is 
unknown).
+                maybeConvertDefaultStringToDate(aDefault, getPropValOrDefault,
+                                                [this]() { return 
getFormatter(); });
+
                 try
                 {
                     xColUpdate->updateObject( aDefault );
diff --git a/forms/source/component/DatabaseForm.hxx 
b/forms/source/component/DatabaseForm.hxx
index 73831a9c67ba..a9c4badb6545 100644
--- a/forms/source/component/DatabaseForm.hxx
+++ b/forms/source/component/DatabaseForm.hxx
@@ -54,6 +54,7 @@
 #include <com/sun/star/beans/XPropertyContainer.hpp>
 #include <com/sun/star/beans/XPropertyAccess.hpp>
 #include <com/sun/star/sdbc/XWarningsSupplier.hpp>
+#include <com/sun/star/util/XNumberFormatter.hpp>
 
 
 #include <tools/link.hxx>
@@ -518,6 +519,9 @@ private:
     void    impl_construct();
 
     DECL_LINK( OnTimeout, Timer*, void );
+
+    css::uno::Reference<css::util::XNumberFormatter> getFormatter();
+
 protected:
     using OPropertySetHelper::getPropertyValues;
 };
commit 5633027b0d1af9c627d250b32284901d9bae20c7
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sun Jul 20 20:02:35 2025 +0500
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Sun Aug 10 11:16:36 2025 +0200

    Flatten ODatabaseForm::reset_impl a bit
    
    Change-Id: I47ad680ef80ed5ed40b329ff83d2c38506a64d54
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188085
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188681

diff --git a/forms/source/component/DatabaseForm.cxx 
b/forms/source/component/DatabaseForm.cxx
index 999bc986bf07..e45842e02764 100644
--- a/forms/source/component/DatabaseForm.cxx
+++ b/forms/source/component/DatabaseForm.cxx
@@ -1961,26 +1961,26 @@ void ODatabaseForm::reset_impl(bool 
_bApproveByListeners)
                     xPSI = xColProps->getPropertySetInfo( );
 
                 static constexpr OUString PROPERTY_CONTROLDEFAULT = 
u"ControlDefault"_ustr;
-                if ( xPSI.is() && xPSI->hasPropertyByName( 
PROPERTY_CONTROLDEFAULT ) )
-                {
-                    Any aDefault = xColProps->getPropertyValue( 
PROPERTY_CONTROLDEFAULT );
+                if (!xPSI || !xPSI->hasPropertyByName(PROPERTY_CONTROLDEFAULT))
+                    continue;
 
-                    bool bReadOnly = false;
-                    if ( xPSI->hasPropertyByName( PROPERTY_ISREADONLY ) )
-                        xColProps->getPropertyValue( PROPERTY_ISREADONLY ) >>= 
bReadOnly;
+                Any aDefault = xColProps->getPropertyValue( 
PROPERTY_CONTROLDEFAULT );
+                if (!aDefault.hasValue())
+                    continue;
 
-                    if ( !bReadOnly )
-                    {
-                        try
-                        {
-                            if ( aDefault.hasValue() )
-                                xColUpdate->updateObject( aDefault );
-                        }
-                        catch(const Exception&)
-                        {
-                            DBG_UNHANDLED_EXCEPTION("forms.component");
-                        }
-                    }
+                bool bReadOnly = false;
+                if ( xPSI->hasPropertyByName( PROPERTY_ISREADONLY ) )
+                    xColProps->getPropertyValue( PROPERTY_ISREADONLY ) >>= 
bReadOnly;
+                if (bReadOnly)
+                    continue;
+
+                try
+                {
+                    xColUpdate->updateObject( aDefault );
+                }
+                catch(const Exception&)
+                {
+                    DBG_UNHANDLED_EXCEPTION("forms.component");
                 }
             }
         }

Reply via email to