[Libreoffice-commits] core.git: dbaccess/CppunitTest_dbaccess_hsqlbinary_import.mk dbaccess/Library_dbahsql.mk dbaccess/Module_dbaccess.mk dbaccess/qa dbaccess/source

Tamas Bunth tamas.bunth at collabora.co.uk
Thu Mar 29 09:08:15 UTC 2018


 dbaccess/CppunitTest_dbaccess_hsqlbinary_import.mk |  106 +++++++++++++++++++++
 dbaccess/Library_dbahsql.mk                        |    5 
 dbaccess/Module_dbaccess.mk                        |    1 
 dbaccess/qa/unit/data/hsqldb_migration_test.odb    |binary
 dbaccess/qa/unit/hsql_binary_import.cxx            |   94 ++++++++++++++++++
 dbaccess/source/filter/hsqldb/fbcreateparser.cxx   |   10 +
 dbaccess/source/filter/hsqldb/rowinputbinary.cxx   |   55 +++++++---
 7 files changed, 253 insertions(+), 18 deletions(-)

New commits:
commit 606cf347404f86ba3d6c94058eb4c470e9e4b596
Author: Tamas Bunth <tamas.bunth at collabora.co.uk>
Date:   Sat Mar 24 18:56:11 2018 +0100

    dbahsql: Unit test for binary import
    
    Also fix bugs shown by the unit test
    
    Use boost date/time instead of std, because std::tm cannot handle dates
    before 1970.
    
    Change-Id: I7f5dbb3d828a591a4b51c7204dc3bd39fefc42ff
    Reviewed-on: https://gerrit.libreoffice.org/51804
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Tamás Bunth <btomi96 at gmail.com>

diff --git a/dbaccess/CppunitTest_dbaccess_hsqlbinary_import.mk b/dbaccess/CppunitTest_dbaccess_hsqlbinary_import.mk
new file mode 100644
index 000000000000..b23e4801f234
--- /dev/null
+++ b/dbaccess/CppunitTest_dbaccess_hsqlbinary_import.mk
@@ -0,0 +1,106 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,dbaccess_hsql_binary_import))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,dbaccess_hsql_binary_import, \
+    dbaccess/qa/unit/hsql_binary_import \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,dbaccess_hsql_binary_import, \
+    basegfx \
+    comphelper \
+    cppu \
+    cppuhelper \
+    dba \
+	dbahsql \
+    dbu \
+    sdbt \
+    drawinglayer \
+    editeng \
+    for \
+    forui \
+    i18nlangtag \
+    msfilter \
+    oox \
+    sal \
+    salhelper \
+    sax \
+    sb \
+    sfx \
+    sot \
+    svl \
+    svt \
+    svx \
+    svxcore \
+    test \
+    subsequenttest \
+    tl \
+    tk \
+    ucbhelper \
+	unotest \
+    utl \
+    vbahelper \
+    vcl \
+    xo \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,dbaccess_hsql_binary_import))
+$(eval $(call gb_CppunitTest_use_vcl,dbaccess_hsql_binary_import))
+
+$(eval $(call gb_CppunitTest_set_include,dbaccess_hsql_binary_import,\
+	-I$(SRCDIR)/dbaccess/source/filter/hsqldb \
+    $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_api,dbaccess_hsql_binary_import,\
+    offapi \
+    oovbaapi \
+    udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_components,dbaccess_hsql_binary_import,\
+    basic/util/sb \
+    comphelper/util/comphelp \
+    configmgr/source/configmgr \
+    connectivity/source/drivers/firebird/firebird_sdbc \
+    connectivity/source/manager/sdbc2 \
+    dbaccess/util/dba \
+    dbaccess/util/dbu \
+    dbaccess/util/sdbt \
+    dbaccess/source/filter/xml/dbaxml \
+    filter/source/config/cache/filterconfig1 \
+    forms/util/frm \
+    framework/util/fwk \
+    i18npool/util/i18npool \
+    linguistic/source/lng \
+    oox/util/oox \
+    package/source/xstor/xstor \
+    package/util/package2 \
+    sax/source/expatwrap/expwrap \
+    scripting/source/basprov/basprov \
+    scripting/util/scriptframe \
+    sfx2/util/sfx \
+    sot/util/sot \
+    svl/source/fsstor/fsstorage \
+    svl/util/svl \
+    toolkit/util/tk \
+    ucb/source/core/ucb1 \
+    ucb/source/ucp/file/ucpfile1 \
+    ucb/source/ucp/tdoc/ucptdoc1 \
+    unotools/util/utl \
+    unoxml/source/rdf/unordf \
+    unoxml/source/service/unoxml \
+    uui/util/uui \
+    xmloff/util/xo \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,dbaccess_hsql_binary_import))
+
+# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/Library_dbahsql.mk b/dbaccess/Library_dbahsql.mk
index bbcdea138a3e..ec684b32136b 100644
--- a/dbaccess/Library_dbahsql.mk
+++ b/dbaccess/Library_dbahsql.mk
@@ -14,7 +14,10 @@ $(eval $(call gb_Library_set_include,dbahsql,\
     -I$(WORKDIR)/YaccTarget/connectivity/source/parse \
 ))
 
-$(eval $(call gb_Library_use_external,dbahsql,boost_headers))
+$(eval $(call gb_Library_use_externals,dbahsql,\
+	boost_headers \
+	boost_date_time \
+))
 
 $(eval $(call gb_Library_set_precompiled_header,dbahsql,$(SRCDIR)/dbaccess/inc/pch/precompiled_dbahsql))
 
diff --git a/dbaccess/Module_dbaccess.mk b/dbaccess/Module_dbaccess.mk
index a8ecb1060c43..0eb7bf97c349 100644
--- a/dbaccess/Module_dbaccess.mk
+++ b/dbaccess/Module_dbaccess.mk
@@ -45,6 +45,7 @@ $(eval $(call gb_Module_add_check_targets,dbaccess,\
 	CppunitTest_dbaccess_nolib_save \
 	CppunitTest_dbaccess_macros_test \
 	CppunitTest_dbaccess_hsqlschema_import \
+	CppunitTest_dbaccess_hsqlbinary_import \
 ))
 
 ifeq ($(ENABLE_JAVA),TRUE)
diff --git a/dbaccess/qa/unit/data/hsqldb_migration_test.odb b/dbaccess/qa/unit/data/hsqldb_migration_test.odb
new file mode 100644
index 000000000000..99b6b5d9a69d
Binary files /dev/null and b/dbaccess/qa/unit/data/hsqldb_migration_test.odb differ
diff --git a/dbaccess/qa/unit/hsql_binary_import.cxx b/dbaccess/qa/unit/hsql_binary_import.cxx
new file mode 100644
index 000000000000..3afe7bd55396
--- /dev/null
+++ b/dbaccess/qa/unit/hsql_binary_import.cxx
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "dbtest_base.cxx"
+
+#include <hsqlimport.hxx>
+
+#include <osl/process.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <test/unoapi_test.hxx>
+#include <svtools/miscopt.hxx>
+
+using namespace dbahsql;
+
+class HsqlBinaryImportTest : public DBTestBase
+{
+public:
+    void testBinaryImport();
+
+    virtual void setUp() override;
+
+    CPPUNIT_TEST_SUITE(HsqlBinaryImportTest);
+
+    CPPUNIT_TEST(testBinaryImport);
+
+    CPPUNIT_TEST_SUITE_END();
+};
+
+void HsqlBinaryImportTest::setUp()
+{
+    DBTestBase::setUp();
+    SvtMiscOptions aMiscOptions;
+    aMiscOptions.SetExperimentalMode(true);
+    osl_setEnvironment(OUString{ "DBACCESS_HSQL_MIGRATION" }.pData, OUString{ "1" }.pData);
+}
+
+void HsqlBinaryImportTest::testBinaryImport()
+{
+    uno::Reference<XOfficeDatabaseDocument> xDocument
+        = getDocumentForFileName("hsqldb_migration_test.odb");
+
+    uno::Reference<XConnection> xConnection = getConnectionForDocument(xDocument);
+    // at this point migration is already done
+
+    uno::Reference<XStatement> statement = xConnection->createStatement();
+    OUString sql{ "SELECT \"ID\", \"Power_value\", \"Power_name\", \"Retired\", "
+                  "\"Birth_date\" FROM \"TestTable\" ORDER BY \"ID\"" };
+
+    uno::Reference<XResultSet> xRes = statement->executeQuery(sql);
+    uno::Reference<XRow> xRow(xRes, UNO_QUERY_THROW);
+
+    // assert first row
+    xRes->next();
+    constexpr sal_Int16 idExpected = 1;
+    CPPUNIT_ASSERT_EQUAL(idExpected, xRow->getShort(1));
+    CPPUNIT_ASSERT_EQUAL(OUString{ "45.32" }, xRow->getString(2)); // numeric
+    CPPUNIT_ASSERT_EQUAL(OUString{ "laser eye" }, xRow->getString(3)); // varchar
+    CPPUNIT_ASSERT(xRow->getBoolean(4)); // boolean
+
+    css::util::Date date = xRow->getDate(5);
+
+    CPPUNIT_ASSERT_EQUAL(sal_uInt16{ 15 }, date.Day);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt16{ 1 }, date.Month);
+    CPPUNIT_ASSERT_EQUAL(sal_Int16{ 1996 }, date.Year);
+
+    // assert second row
+    xRes->next();
+    constexpr sal_Int16 secondIdExpected = 2;
+    CPPUNIT_ASSERT_EQUAL(secondIdExpected, xRow->getShort(1)); // ID
+    CPPUNIT_ASSERT_EQUAL(OUString{ "54.12" }, xRow->getString(2)); // numeric
+    CPPUNIT_ASSERT_EQUAL(OUString{ "telekinesis" }, xRow->getString(3)); // varchar
+    CPPUNIT_ASSERT(!xRow->getBoolean(4)); // boolean
+
+    date = xRow->getDate(5);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt16{ 26 }, date.Day);
+    CPPUNIT_ASSERT_EQUAL(sal_uInt16{ 2 }, date.Month);
+    CPPUNIT_ASSERT_EQUAL(sal_Int16{ 1998 }, date.Year);
+
+    closeDocument(uno::Reference<lang::XComponent>(xDocument, uno::UNO_QUERY));
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(HsqlBinaryImportTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/dbaccess/source/filter/hsqldb/fbcreateparser.cxx b/dbaccess/source/filter/hsqldb/fbcreateparser.cxx
index 64f51e6ca6d6..a20321dc8af5 100644
--- a/dbaccess/source/filter/hsqldb/fbcreateparser.cxx
+++ b/dbaccess/source/filter/hsqldb/fbcreateparser.cxx
@@ -112,7 +112,15 @@ OUString FbCreateStmtParser::compose() const
         lcl_appendWithSpace(sSql, columnIter->getName());
         lcl_appendWithSpace(sSql, lcl_DataTypetoFbTypeName(columnIter->getDataType()));
 
-        const std::vector<sal_Int32> params = columnIter->getParams();
+        std::vector<sal_Int32> params{ columnIter->getParams() };
+
+        if (columnIter->getDataType() == DataType::NUMERIC
+            || columnIter->getDataType() == DataType::DECIMAL)
+        {
+            // max precision is 18 here
+            if (params.at(0) > 18)
+                params[0] = 18;
+        }
 
         // Firebird SQL dialect does not like parameters for TIMESTAMP
         if (params.size() > 0 && columnIter->getDataType() != DataType::TIMESTAMP)
diff --git a/dbaccess/source/filter/hsqldb/rowinputbinary.cxx b/dbaccess/source/filter/hsqldb/rowinputbinary.cxx
index a69d696bf1b2..492f3c4ac6d5 100644
--- a/dbaccess/source/filter/hsqldb/rowinputbinary.cxx
+++ b/dbaccess/source/filter/hsqldb/rowinputbinary.cxx
@@ -28,7 +28,8 @@
 #include <unotools/ucbstreamhelper.hxx>
 #include <tools/stream.hxx>
 #include <rtl/ustrbuf.hxx>
-#include <ctime>
+
+#include <boost/date_time/posix_time/posix_time.hpp>
 
 namespace
 {
@@ -75,7 +76,7 @@ OUString lcl_double_dabble(const std::vector<sal_uInt8>& bytes)
 
     auto it = scratch.begin();
     /* Remove leading zeros from the scratch space. */
-    while (*it != 0)
+    while (*it == 0)
     {
         it = scratch.erase(it);
     }
@@ -113,6 +114,20 @@ OUString lcl_makeStringFromBigint(const std::vector<sal_uInt8> bytes)
     sRet.append(sNum);
     return sRet.makeStringAndClear();
 }
+
+OUString lcl_putDot(const OUString& sNum, sal_Int32 nScale)
+{
+    OUStringBuffer sBuf{ sNum };
+    if (nScale >= sNum.getLength())
+    {
+        sal_Int32 nNullsToAppend = nScale - sNum.getLength();
+        for (sal_Int32 i = 0; i < nNullsToAppend; ++i)
+            sBuf.insert(0, "0");
+    }
+    if (nScale > 0)
+        sBuf.insert(sBuf.getLength() - 1 - nScale, ".");
+    return sBuf.makeStringAndClear();
+}
 }
 
 namespace dbahsql
@@ -120,6 +135,8 @@ namespace dbahsql
 using namespace css::uno;
 using namespace css::sdbc;
 using namespace css::io;
+using namespace boost::posix_time;
+using namespace boost::gregorian;
 
 typedef std::vector<sal_Int32> ColumnTypeVector;
 
@@ -296,7 +313,8 @@ std::vector<Any> HsqlRowInputStream::readOneRow(const ColumnTypeVector& nColType
                 m_pStream->ReadInt32(nScale);
 
                 Sequence<Any> result(2);
-                result[0] <<= lcl_makeStringFromBigint(aBytes);
+                OUString sNum = lcl_makeStringFromBigint(aBytes);
+                result[0] <<= lcl_putDot(sNum, nScale);
                 result[1] <<= nSize;
                 aData.push_back(makeAny(result));
             }
@@ -305,11 +323,13 @@ std::vector<Any> HsqlRowInputStream::readOneRow(const ColumnTypeVector& nColType
             {
                 sal_Int64 value = 0;
                 m_pStream->ReadInt64(value); // in millisec, from 1970
-                std::time_t nEpochSec = value / 1000;
-                std::tm* tm = std::gmtime(&nEpochSec);
-                css::util::Date date(tm->tm_mday, tm->tm_mon + 1,
-                                     tm->tm_year + 1900); // day, month, year
-                aData.push_back(makeAny(date));
+                ptime epoch = time_from_string("1970-01-01 00:00:00.000");
+                ptime time = epoch + milliseconds(value);
+                date asDate = time.date();
+
+                css::util::Date loDate(asDate.day(), asDate.month(),
+                                       asDate.year()); // day, month, year
+                aData.push_back(makeAny(loDate));
             }
             break;
             case DataType::TIME:
@@ -324,19 +344,22 @@ std::vector<Any> HsqlRowInputStream::readOneRow(const ColumnTypeVector& nColType
             {
                 sal_Int64 nEpochMillis = 0;
                 m_pStream->ReadInt64(nEpochMillis);
-                std::time_t nEpochSec = nEpochMillis / 1000;
-                std::tm* tm = std::gmtime(&nEpochSec);
+                ptime epoch = time_from_string("1970-01-01 00:00:00.000");
+                ptime time = epoch + milliseconds(nEpochMillis);
+                date asDate = time.date();
 
                 sal_Int32 nNanos = 0;
                 m_pStream->ReadInt32(nNanos);
+
+                // convert into LO internal representation of dateTime
                 css::util::DateTime dateTime;
                 dateTime.NanoSeconds = nNanos;
-                dateTime.Seconds = tm->tm_sec;
-                dateTime.Minutes = tm->tm_min;
-                dateTime.Hours = tm->tm_hour;
-                dateTime.Day = tm->tm_mday;
-                dateTime.Month = tm->tm_mon + 1; // indexed from 0
-                dateTime.Year = 1900 + tm->tm_year;
+                dateTime.Seconds = time.time_of_day().seconds();
+                dateTime.Minutes = time.time_of_day().minutes();
+                dateTime.Hours = time.time_of_day().hours();
+                dateTime.Day = asDate.day();
+                dateTime.Month = asDate.month();
+                dateTime.Year = asDate.year();
                 aData.push_back(makeAny(dateTime));
             }
             break;


More information about the Libreoffice-commits mailing list