diff options
author | Tamas Bunth <tamas.bunth@collabora.co.uk> | 2018-03-08 10:50:18 +0100 |
---|---|---|
committer | Tamás Bunth <btomi96@gmail.com> | 2018-03-10 21:15:05 +0100 |
commit | 6039d2463b4cc503b963811b3b1471de3291ee09 (patch) | |
tree | 1f95b47d17a5fad60c2c5305bff6ddf786a3bec7 /dbaccess | |
parent | 5f23f94cdef660909e105176a8c7ae83780baa71 (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>
Diffstat (limited to 'dbaccess')
-rw-r--r-- | dbaccess/source/filter/hsqldb/hsqlimport.cxx | 12 | ||||
-rw-r--r-- | dbaccess/source/filter/hsqldb/rowinputbinary.cxx | 95 |
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: |