summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamas Bunth <tamas.bunth@collabora.co.uk>2018-03-08 10:50:18 +0100
committerTamás Bunth <btomi96@gmail.com>2018-03-10 21:15:05 +0100
commit6039d2463b4cc503b963811b3b1471de3291ee09 (patch)
tree1f95b47d17a5fad60c2c5305bff6ddf786a3bec7
parent5f23f94cdef660909e105176a8c7ae83780baa71 (diff)
dbahsql: Add numeric/decimal import
Change-Id: Icba170d586d35f890d5232463f89d547d526d885 Reviewed-on: https://gerrit.libreoffice.org/50937 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Tamás Bunth <btomi96@gmail.com>
-rw-r--r--dbaccess/source/filter/hsqldb/hsqlimport.cxx12
-rw-r--r--dbaccess/source/filter/hsqldb/rowinputbinary.cxx95
2 files changed, 104 insertions, 3 deletions
diff --git a/dbaccess/source/filter/hsqldb/hsqlimport.cxx b/dbaccess/source/filter/hsqldb/hsqlimport.cxx
index 12d2ede81870..cc806b313e9a 100644
--- a/dbaccess/source/filter/hsqldb/hsqlimport.cxx
+++ b/dbaccess/source/filter/hsqldb/hsqlimport.cxx
@@ -143,8 +143,16 @@ void lcl_setParams(const RowVector& row, Reference<XParameters>& xParam,
}
case DataType::NUMERIC:
case DataType::DECIMAL:
- // TODO
- break;
+ {
+ Sequence<Any> aNumeric;
+ if (row.at(i) >>= aNumeric)
+ {
+ sal_Int32 nScale = 0;
+ if (aNumeric[1] >>= nScale)
+ xParam->setObjectWithInfo(i + 1, aNumeric[0], rColTypes.at(i), nScale);
+ }
+ }
+ break;
case DataType::DATE:
// TODO
break;
diff --git a/dbaccess/source/filter/hsqldb/rowinputbinary.cxx b/dbaccess/source/filter/hsqldb/rowinputbinary.cxx
index a0f52b0601a1..b657abd36d52 100644
--- a/dbaccess/source/filter/hsqldb/rowinputbinary.cxx
+++ b/dbaccess/source/filter/hsqldb/rowinputbinary.cxx
@@ -24,6 +24,92 @@
#include <unotools/ucbstreamhelper.hxx>
#include <tools/stream.hxx>
+#include <rtl/ustrbuf.hxx>
+
+namespace
+{
+/**
+ * Converts binary represented big integer value to BCD (Binary Coded
+ * Decimal), and returns a string representation of the number.
+ *
+ * Bytes[0] is the most significant part of the number.
+ */
+OUString lcl_double_dabble(const std::vector<sal_uInt8>& bytes)
+{
+ size_t nbits = 8 * bytes.size(); // length of array in bits
+ size_t nscratch = nbits / 3; // length of scratch in bytes
+ std::vector<char> scratch(nscratch, 0);
+ size_t smin = nscratch - 2; // speed optimization
+
+ for (size_t i = 0; i < bytes.size(); ++i)
+ {
+ for (size_t j = 0; j < 8; ++j)
+ {
+ /* This bit will be shifted in on the right. */
+ int shifted_in = (bytes[i] & (1 << (7 - j))) ? 1 : 0;
+
+ /* Add 3 everywhere that scratch[k] >= 5. */
+ for (size_t k = smin; k < nscratch; ++k)
+ scratch[k] += (scratch[k] >= 5) ? 3 : 0;
+
+ /* Shift scratch to the left by one position. */
+ if (scratch[smin] >= 8)
+ smin -= 1;
+ for (size_t k = smin; k < nscratch - 1; ++k)
+ {
+ scratch[k] <<= 1;
+ scratch[k] &= 0xF;
+ scratch[k] |= (scratch[k + 1] >= 8) ? 1 : 0;
+ }
+
+ /* Shift in the new bit from arr. */
+ scratch[nscratch - 1] <<= 1;
+ scratch[nscratch - 1] &= 0xF;
+ scratch[nscratch - 1] |= shifted_in;
+ }
+ }
+
+ auto it = scratch.begin();
+ /* Remove leading zeros from the scratch space. */
+ while (*it != 0)
+ {
+ it = scratch.erase(it);
+ }
+
+ /* Convert the scratch space from BCD digits to ASCII. */
+ for (auto& digit : scratch)
+ digit += '0';
+
+ /* Resize and return the resulting string. */
+ return rtl::OStringToOUString(OString(scratch.data(), scratch.size()), RTL_TEXTENCODING_UTF8);
+}
+
+OUString lcl_makeStringFromBigint(const std::vector<sal_uInt8> bytes)
+{
+ std::vector<sal_uInt8> aBytes{ bytes };
+
+ OUStringBuffer sRet;
+ // two's complement
+ if (aBytes[0] == 1)
+ {
+ sRet.append("-");
+ for (auto& byte : aBytes)
+ byte = ~byte;
+ // add 1 to byte array
+ // FIXME e.g. 10000 valid ?
+ for (size_t i = aBytes.size() - 1; i != 0; ++i)
+ {
+ aBytes[i] += 1;
+ if (aBytes[i] != 0)
+ break;
+ }
+ }
+ // convert binary to BCD
+ OUString sNum = lcl_double_dabble(aBytes);
+ sRet.append(sNum);
+ return sRet.makeStringAndClear();
+}
+}
namespace dbahsql
{
@@ -200,8 +286,15 @@ std::vector<Any> HsqlRowInputStream::readOneRow(const ColumnTypeVector& nColType
std::vector<sal_uInt8> aBytes(nSize);
m_pStream->ReadBytes(aBytes.data(), nSize);
+ assert(aBytes.size() > 0);
+
+ sal_Int32 nScale = 0;
+ m_pStream->ReadInt32(nScale);
- // TODO make a numeric out of this.
+ Sequence<Any> result(2);
+ result[0] <<= lcl_makeStringFromBigint(aBytes);
+ result[1] <<= nSize;
+ aData.push_back(makeAny(result));
}
break;
case DataType::DATE: