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

Tamas Bunth tamas.bunth at collabora.co.uk
Mon Mar 5 09:18:35 UTC 2018


 dbaccess/Library_dbahsql.mk                      |    5 
 dbaccess/source/filter/hsqldb/columndef.hxx      |   10 
 dbaccess/source/filter/hsqldb/createparser.hxx   |   10 
 dbaccess/source/filter/hsqldb/fbcreateparser.hxx |   10 
 dbaccess/source/filter/hsqldb/hsqlbinarynode.cxx |   61 +++++
 dbaccess/source/filter/hsqldb/hsqlbinarynode.hxx |   39 +++
 dbaccess/source/filter/hsqldb/hsqlimport.cxx     |  241 +++++++++++++++++++++-
 dbaccess/source/filter/hsqldb/hsqlimport.hxx     |   20 -
 dbaccess/source/filter/hsqldb/parseschema.cxx    |   26 ++
 dbaccess/source/filter/hsqldb/parseschema.hxx    |   17 -
 dbaccess/source/filter/hsqldb/rowinputbinary.cxx |  246 +++++++++++++++++++++++
 dbaccess/source/filter/hsqldb/rowinputbinary.hxx |   46 ++++
 12 files changed, 670 insertions(+), 61 deletions(-)

New commits:
commit 60ac7418747530a006894a7941c67c5006d6158c
Author: Tamas Bunth <tamas.bunth at collabora.co.uk>
Date:   Wed Feb 28 21:40:06 2018 +0100

    HSQLDB Binary import
    
    C++ implementation of reading HSQL's binary file format. This file
    contains the actual rows for the tables, represented in an AVL tree.
    
    Import starts from HsqlImporter, which calls to SchemaParser for some
    metadata (the positions of the trees in "data" file). After that it goes
    through the tree and read up the rows using HsqlRowInputStream.
    
    Finally, it uses sdbc's XPreparedStatement to insert the rows to the
    actual database.
    
    Change-Id: If4b17572e5989c218d45880bc3fd5a8820bb4101
    Reviewed-on: https://gerrit.libreoffice.org/50536
    Reviewed-by: Tamás Bunth <btomi96 at gmail.com>
    Tested-by: Tamás Bunth <btomi96 at gmail.com>

diff --git a/dbaccess/Library_dbahsql.mk b/dbaccess/Library_dbahsql.mk
index f85660e6b3a8..bbcdea138a3e 100644
--- a/dbaccess/Library_dbahsql.mk
+++ b/dbaccess/Library_dbahsql.mk
@@ -27,6 +27,9 @@ $(eval $(call gb_Library_use_libraries,dbahsql,\
     sal \
     salhelper \
     dbtools \
+    ucbhelper \
+    utl \
+    tl \
 ))
 
 $(eval $(call gb_Library_add_exception_objects,dbahsql,\
@@ -35,6 +38,8 @@ $(eval $(call gb_Library_add_exception_objects,dbahsql,\
     dbaccess/source/filter/hsqldb/createparser \
     dbaccess/source/filter/hsqldb/columndef \
     dbaccess/source/filter/hsqldb/fbcreateparser \
+    dbaccess/source/filter/hsqldb/rowinputbinary \
+    dbaccess/source/filter/hsqldb/hsqlbinarynode \
 ))
 
 # vim: set noet sw=4 ts=4:
diff --git a/dbaccess/source/filter/hsqldb/columndef.hxx b/dbaccess/source/filter/hsqldb/columndef.hxx
index 4c46ac10a5ce..bded07bf5b4c 100644
--- a/dbaccess/source/filter/hsqldb/columndef.hxx
+++ b/dbaccess/source/filter/hsqldb/columndef.hxx
@@ -5,16 +5,6 @@
  * 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/.
- *
- * This file incorporates work covered by the following license notice:
- *
- *   Licensed to the Apache Software Foundation (ASF) under one or more
- *   contributor license agreements. See the NOTICE file distributed
- *   with this work for additional information regarding copyright
- *   ownership. The ASF licenses this file to you under the Apache
- *   License, Version 2.0 (the "License"); you may not use this file
- *   except in compliance with the License. You may obtain a copy of
- *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
 #ifndef INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_COLUMNDEF_HXX
diff --git a/dbaccess/source/filter/hsqldb/createparser.hxx b/dbaccess/source/filter/hsqldb/createparser.hxx
index 4bc4bd2343b6..03532a1d197f 100644
--- a/dbaccess/source/filter/hsqldb/createparser.hxx
+++ b/dbaccess/source/filter/hsqldb/createparser.hxx
@@ -5,16 +5,6 @@
  * 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/.
- *
- * This file incorporates work covered by the following license notice:
- *
- *   Licensed to the Apache Software Foundation (ASF) under one or more
- *   contributor license agreements. See the NOTICE file distributed
- *   with this work for additional information regarding copyright
- *   ownership. The ASF licenses this file to you under the Apache
- *   License, Version 2.0 (the "License"); you may not use this file
- *   except in compliance with the License. You may obtain a copy of
- *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
 #ifndef INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_CREATEPARSER_HXX
diff --git a/dbaccess/source/filter/hsqldb/fbcreateparser.hxx b/dbaccess/source/filter/hsqldb/fbcreateparser.hxx
index 02255089c1ca..fec8c6f9c34b 100644
--- a/dbaccess/source/filter/hsqldb/fbcreateparser.hxx
+++ b/dbaccess/source/filter/hsqldb/fbcreateparser.hxx
@@ -5,16 +5,6 @@
  * 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/.
- *
- * This file incorporates work covered by the following license notice:
- *
- *   Licensed to the Apache Software Foundation (ASF) under one or more
- *   contributor license agreements. See the NOTICE file distributed
- *   with this work for additional information regarding copyright
- *   ownership. The ASF licenses this file to you under the Apache
- *   License, Version 2.0 (the "License"); you may not use this file
- *   except in compliance with the License. You may obtain a copy of
- *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
 #ifndef INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_FBCREATEPARSER_HXX
diff --git a/dbaccess/source/filter/hsqldb/hsqlbinarynode.cxx b/dbaccess/source/filter/hsqldb/hsqlbinarynode.cxx
new file mode 100644
index 000000000000..8a8cf1a9a20b
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/hsqlbinarynode.cxx
@@ -0,0 +1,61 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "hsqlbinarynode.hxx"
+#include "rowinputbinary.hxx"
+
+#include <cppuhelper/implbase.hxx>
+#include <vector>
+
+namespace dbahsql
+{
+using ColumnTypeVector = std::vector<sal_Int32>;
+
+HsqlBinaryNode::HsqlBinaryNode(sal_Int32 nPos)
+    : m_nPos(nPos)
+{
+}
+
+void HsqlBinaryNode::readChildren(HsqlRowInputStream& input)
+{
+    SvStream* pStream = input.getInputStream();
+    if (!pStream)
+        return;
+
+    pStream->Seek(m_nPos + 8); // skip size and balance
+    pStream->ReadInt32(m_nLeft);
+    if (m_nLeft <= 0)
+        m_nLeft = -1;
+    pStream->ReadInt32(m_nRight);
+    if (m_nRight <= 0)
+        m_nRight = -1;
+}
+
+std::vector<css::uno::Any> HsqlBinaryNode::readRow(HsqlRowInputStream& input,
+                                                   const ColumnTypeVector& aColTypes)
+{
+    input.seek(m_nPos + 20); // go to data
+    return input.readOneRow(aColTypes);
+}
+
+sal_Int32 HsqlBinaryNode::getLeft() const { return m_nLeft; }
+sal_Int32 HsqlBinaryNode::getRight() const { return m_nRight; }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/hsqlbinarynode.hxx b/dbaccess/source/filter/hsqldb/hsqlbinarynode.hxx
new file mode 100644
index 000000000000..7c3631a6c8b2
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/hsqlbinarynode.hxx
@@ -0,0 +1,39 @@
+/* -*- 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/.
+ */
+
+#ifndef INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_HSQLBINARYNODE_HXX
+#define INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_HSQLBINARYNODE_HXX
+
+#include <vector>
+#include <cppuhelper/implbase.hxx>
+
+#include "rowinputbinary.hxx"
+
+namespace dbahsql
+{
+class HsqlBinaryNode
+{
+private:
+    sal_Int32 m_nLeft = -1;
+    sal_Int32 m_nRight = -1;
+    sal_Int32 m_nPos = -1;
+
+public:
+    HsqlBinaryNode(sal_Int32 nPos);
+    void readChildren(HsqlRowInputStream& input);
+    sal_Int32 getLeft() const;
+    sal_Int32 getRight() const;
+    std::vector<css::uno::Any> readRow(HsqlRowInputStream& rInput,
+                                       const std::vector<sal_Int32>& aColTypes);
+};
+}
+
+#endif // INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_HSQLBINARYNODE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/hsqlimport.cxx b/dbaccess/source/filter/hsqldb/hsqlimport.cxx
index be0e1df4a538..c2483e694a8d 100644
--- a/dbaccess/source/filter/hsqldb/hsqlimport.cxx
+++ b/dbaccess/source/filter/hsqldb/hsqlimport.cxx
@@ -18,15 +18,156 @@
  */
 
 #include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/WrongFormatException.hpp>
+
 #include <com/sun/star/sdbc/XConnection.hpp>
+#include <com/sun/star/sdbc/XParameters.hpp>
+#include <com/sun/star/sdbc/DataType.hpp>
+
+#include <comphelper/string.hxx>
 
 #include "hsqlimport.hxx"
 #include "parseschema.hxx"
+#include "rowinputbinary.hxx"
 
-namespace dbahsql
+namespace
 {
+using namespace ::comphelper;
+using namespace css::io;
 using namespace css::uno;
 using namespace css::sdbc;
+
+using ColumnTypeVector = std::vector<sal_Int32>;
+using RowVector = std::vector<Any>;
+using IndexVector = std::vector<sal_Int32>;
+
+class IndexStmtParser
+{
+private:
+    OUString m_sql;
+
+public:
+    IndexStmtParser(const OUString& sSql)
+        : m_sql(sSql)
+    {
+    }
+
+    bool isIndexStatement() const
+    {
+        return m_sql.startsWith("SET TABLE") && m_sql.indexOf("INDEX") >= 0;
+    }
+
+    IndexVector getIndexes() const
+    {
+        assert(isIndexStatement());
+
+        OUString sIndexPart = m_sql.copy(m_sql.indexOf("INDEX") + 5);
+        sal_Int32 nQuotePos = sIndexPart.indexOf("'") + 1;
+        OUString sIndexNums = sIndexPart.copy(nQuotePos, sIndexPart.lastIndexOf("'") - nQuotePos);
+
+        std::vector<OUString> sIndexes = string::split(sIndexNums, u' ');
+        IndexVector indexes;
+        for (const auto& sIndex : sIndexes)
+            indexes.push_back(sIndex.toInt32());
+
+        return indexes;
+    }
+
+    OUString getTableName() const
+    {
+        // SET TABLE <tableName>
+        return string::split(m_sql, u' ')[2];
+    }
+};
+
+void lcl_setParams(const RowVector& row, Reference<XParameters>& xParam,
+                   const ColumnTypeVector& rColTypes)
+{
+    assert(row.size() == rColTypes.size());
+    for (size_t i = 0; i < rColTypes.size(); ++i)
+    {
+        switch (rColTypes.at(i))
+        {
+            case DataType::CHAR:
+            case DataType::VARCHAR:
+            case DataType::LONGVARCHAR:
+            {
+                OUString sVal;
+                if (row.at(i) >>= sVal)
+                {
+                    xParam->setString(i + 1, sVal);
+                }
+            }
+            break;
+            case DataType::TINYINT:
+            case DataType::SMALLINT:
+            {
+                sal_Int16 nVal;
+                if (row.at(i) >>= nVal)
+                {
+                    xParam->setShort(i + 1, nVal);
+                }
+            }
+            break;
+            case DataType::INTEGER:
+            {
+                sal_Int32 nVal;
+                if (row.at(i) >>= nVal)
+                {
+                    xParam->setInt(i + 1, nVal);
+                }
+            }
+            break;
+            case DataType::BIGINT:
+                break;
+            case DataType::REAL:
+            case DataType::FLOAT:
+            case DataType::DOUBLE:
+                break;
+            case DataType::NUMERIC:
+            case DataType::DECIMAL:
+                break;
+            case DataType::DATE:
+                break;
+            case DataType::TIME:
+                break;
+            case DataType::TIMESTAMP:
+                break;
+            case DataType::BOOLEAN:
+                break;
+            case DataType::OTHER:
+                break;
+            case DataType::BINARY:
+            case DataType::VARBINARY:
+            case DataType::LONGVARBINARY:
+                break;
+            default:
+                throw WrongFormatException();
+        }
+    }
+}
+
+OUString lcl_createInsertStatement(const OUString& sTableName, sal_Int32 nColumnCount)
+{
+    assert(nColumnCount > 0);
+    OUStringBuffer sql("INSERT INTO ");
+    sql.append(sTableName);
+    sql.append(" VALUES (");
+    for (int i = 0; i < nColumnCount - 1; ++i)
+    {
+        sql.append("?,");
+    }
+    sql.append("?)");
+    return sql.makeStringAndClear();
+}
+
+} // unnamed namespace
+
+namespace dbahsql
+{
 using namespace css::embed;
 
 HsqlImporter::HsqlImporter(Reference<XConnection>& rConnection, const Reference<XStorage>& rStorage)
@@ -36,7 +177,81 @@ HsqlImporter::HsqlImporter(Reference<XConnection>& rConnection, const Reference<
     m_xStorage.set(rStorage);
 }
 
-void HsqlImporter::importSchema()
+void HsqlImporter::insertRow(const RowVector& xRows, const OUString& sTableName,
+                             const ColumnTypeVector& rColTypes)
+{
+    OUString sStatement = lcl_createInsertStatement(sTableName, xRows.size());
+    Reference<XPreparedStatement> xStatement = m_rConnection->prepareStatement(sStatement);
+
+    Reference<XParameters> xParameter(xStatement, UNO_QUERY);
+    assert(xParameter.is());
+    xParameter->clearParameters();
+
+    lcl_setParams(xRows, xParameter, rColTypes);
+    xStatement->executeQuery();
+}
+
+void HsqlImporter::processTree(HsqlBinaryNode& rNode, HsqlRowInputStream& rStream,
+                               const ColumnTypeVector& rColTypes, const OUString& sTableName)
+{
+    rNode.readChildren(rStream);
+    std::vector<Any> row = rNode.readRow(rStream, rColTypes);
+    insertRow(row, sTableName, rColTypes);
+
+    sal_Int32 nNext = rNode.getLeft();
+    if (nNext > 0)
+    {
+        HsqlBinaryNode aLeft{ nNext };
+        processTree(aLeft, rStream, rColTypes, sTableName);
+    }
+    nNext = rNode.getRight();
+    if (nNext > 0)
+    {
+        HsqlBinaryNode aRight{ nNext };
+        processTree(aRight, rStream, rColTypes, sTableName);
+    }
+}
+
+/**
+ * Format from the indexed file position is the following:
+ * <Node x20><Row>
+ * Where Node is a 20 byte data, representing the rows in a binary tree:
+ * <Size x4><Balance x4><Left x4> <Right x4><Parent x4>
+ *
+ * Size is the size of <Row>;
+ * Balance: ?
+ * Left/Right/Parent: File postition of the Left/Right/Parent child
+ */
+void HsqlImporter::parseTableRows(const IndexVector& rIndexes,
+                                  const std::vector<sal_Int32>& rColTypes,
+                                  const OUString& sTableName)
+{
+    constexpr char BINARY_FILENAME[] = "data";
+
+    if (!m_xStorage->hasByName(BINARY_FILENAME))
+    {
+        SAL_WARN("dbaccess", "data file does not exist in storage during hsqldb import");
+        assert(false); // TODO throw error
+    }
+
+    Reference<css::io::XStream> xStream(
+        m_xStorage->openStreamElement(BINARY_FILENAME, ElementModes::READ));
+
+    HsqlRowInputStream rowInput;
+    Reference<XInputStream> xInput = xStream->getInputStream();
+    rowInput.setInputStream(xInput);
+    for (const auto& index : rIndexes)
+    {
+        if (index <= 0)
+            break;
+
+        HsqlBinaryNode aNode{ index };
+        processTree(aNode, rowInput, rColTypes, sTableName);
+    }
+    xInput->closeInput();
+}
+
+void HsqlImporter::importHsqlDatabase()
 {
     assert(m_xStorage);
 
@@ -45,12 +260,26 @@ void HsqlImporter::importSchema()
 
     for (auto& sSql : statements)
     {
-        Reference<XStatement> statement = m_rConnection->createStatement();
-        statement->executeQuery(sSql);
+        // SET TABLE ... INDEX ...
+        // These statements tell us the position of the data in the binary data
+        // file
+        IndexStmtParser aIndexParser(sSql);
+        if (aIndexParser.isIndexStatement())
+        {
+            IndexVector aIndexes = aIndexParser.getIndexes();
+            OUString sTableName = aIndexParser.getTableName();
+            std::vector<sal_Int32> aColTypes = parser.getTableColumnTypes(sTableName);
+
+            parseTableRows(aIndexes, aColTypes, sTableName);
+        }
+        else
+        {
+            // other, "normal" statements
+            Reference<XStatement> statement = m_rConnection->createStatement();
+            statement->executeQuery(sSql);
+        }
     }
 }
-
-void HsqlImporter::importHsqlDatabase() { importSchema(); }
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/hsqlimport.hxx b/dbaccess/source/filter/hsqldb/hsqlimport.hxx
index d4887633e184..b40f73079a7e 100644
--- a/dbaccess/source/filter/hsqldb/hsqlimport.hxx
+++ b/dbaccess/source/filter/hsqldb/hsqlimport.hxx
@@ -5,16 +5,6 @@
  * 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/.
- *
- * This file incorporates work covered by the following license notice:
- *
- *   Licensed to the Apache Software Foundation (ASF) under one or more
- *   contributor license agreements. See the NOTICE file distributed
- *   with this work for additional information regarding copyright
- *   ownership. The ASF licenses this file to you under the Apache
- *   License, Version 2.0 (the "License"); you may not use this file
- *   except in compliance with the License. You may obtain a copy of
- *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
 #ifndef INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_HSQLIMPORT_HXX
@@ -23,6 +13,9 @@
 #include <com/sun/star/embed/XStorage.hpp>
 #include <com/sun/star/sdbc/XConnection.hpp>
 
+#include "rowinputbinary.hxx"
+#include "hsqlbinarynode.hxx"
+
 namespace dbahsql
 {
 class SAL_DLLPUBLIC_EXPORT HsqlImporter
@@ -32,7 +25,12 @@ private:
     css::uno::Reference<css::embed::XStorage> m_xStorage;
 
 protected:
-    void importSchema();
+    void insertRow(const std::vector<css::uno::Any>& xRows, const OUString& sTable,
+                   const std::vector<sal_Int32>& rColTypes);
+    void processTree(HsqlBinaryNode& rNode, HsqlRowInputStream& rStream,
+                     const std::vector<sal_Int32>& rColTypes, const OUString& sTableName);
+    void parseTableRows(const std::vector<sal_Int32>& rIndexes,
+                        const std::vector<sal_Int32>& rColTypes, const OUString& sTableName);
 
 public:
     HsqlImporter(css::uno::Reference<css::sdbc::XConnection>& rConnection,
diff --git a/dbaccess/source/filter/hsqldb/parseschema.cxx b/dbaccess/source/filter/hsqldb/parseschema.cxx
index a899fbba913e..5ee2b4d1e2c6 100644
--- a/dbaccess/source/filter/hsqldb/parseschema.cxx
+++ b/dbaccess/source/filter/hsqldb/parseschema.cxx
@@ -31,6 +31,8 @@ using namespace css::io;
 using namespace css::uno;
 using namespace css::embed;
 
+typedef std::vector<sal_Int32> ColumnTypeVector;
+
 SchemaParser::SchemaParser(Reference<XStorage>& rStorage)
     : m_rStorage(rStorage)
 {
@@ -60,16 +62,26 @@ SqlStatementVector SchemaParser::parseSchema()
         // every line contains exactly one DDL statement
         OUString sSql = xTextInput->readLine();
 
-        if (sSql.startsWith("SET") || sSql.startsWith("CREATE USER")
-            || sSql.startsWith("CREATE SCHEMA") || sSql.startsWith("GRANT"))
+        if (sSql.startsWith("SET TABLE") && sSql.indexOf("INDEX") > 0)
+        { // nothing
+        }
+        else if (sSql.startsWith("SET") || sSql.startsWith("CREATE USER")
+                 || sSql.startsWith("CREATE SCHEMA") || sSql.startsWith("GRANT"))
             continue;
-
-        if (sSql.startsWith("CREATE CACHED TABLE") || sSql.startsWith("CREATE TABLE"))
+        else if (sSql.startsWith("CREATE CACHED TABLE") || sSql.startsWith("CREATE TABLE"))
         {
             FbCreateStmtParser aCreateParser;
             aCreateParser.parse(sSql);
 
             sSql = aCreateParser.compose();
+
+            // Store columns for each table
+            ColumnTypeVector colTypes;
+            std::vector<ColumnDefinition> colDefs = aCreateParser.getColumnDef();
+            for (const auto& colDef : colDefs)
+                colTypes.push_back(colDef.getDataType());
+
+            m_ColumnTypes[aCreateParser.getTableName()] = colTypes;
         }
 
         parsedStatements.push_back(sSql);
@@ -77,6 +89,12 @@ SqlStatementVector SchemaParser::parseSchema()
 
     return parsedStatements;
 }
+
+ColumnTypeVector SchemaParser::getTableColumnTypes(const OUString& sTableName) const
+{
+    return m_ColumnTypes.at(sTableName);
 }
 
+} // namespace dbahsql
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/parseschema.hxx b/dbaccess/source/filter/hsqldb/parseschema.hxx
index 6767ce08414a..af97ae578241 100644
--- a/dbaccess/source/filter/hsqldb/parseschema.hxx
+++ b/dbaccess/source/filter/hsqldb/parseschema.hxx
@@ -5,16 +5,6 @@
  * 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/.
- *
- * This file incorporates work covered by the following license notice:
- *
- *   Licensed to the Apache Software Foundation (ASF) under one or more
- *   contributor license agreements. See the NOTICE file distributed
- *   with this work for additional information regarding copyright
- *   ownership. The ASF licenses this file to you under the Apache
- *   License, Version 2.0 (the "License"); you may not use this file
- *   except in compliance with the License. You may obtain a copy of
- *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
 #ifndef INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_PARSECHEMA_HXX
@@ -23,6 +13,7 @@
 #include <com/sun/star/embed/XStorage.hpp>
 #include <com/sun/star/sdbc/XConnection.hpp>
 #include <vector>
+#include <map>
 
 namespace dbahsql
 {
@@ -33,9 +24,15 @@ class SchemaParser
 private:
     css::uno::Reference<css::embed::XStorage>& m_rStorage;
 
+    // column type for each table. It is filled after parsing schema.
+    std::map<OUString, std::vector<sal_Int32>> m_ColumnTypes;
+
 public:
     explicit SchemaParser(css::uno::Reference<css::embed::XStorage>& rStorage);
+
     SqlStatementVector parseSchema();
+
+    std::vector<sal_Int32> getTableColumnTypes(const OUString& sTableName) const;
 };
 }
 
diff --git a/dbaccess/source/filter/hsqldb/rowinputbinary.cxx b/dbaccess/source/filter/hsqldb/rowinputbinary.cxx
new file mode 100644
index 000000000000..37cfa918fef5
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/rowinputbinary.cxx
@@ -0,0 +1,246 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "rowinputbinary.hxx"
+#include <com/sun/star/sdbc/DataType.hpp>
+#include <com/sun/star/io/WrongFormatException.hpp>
+#include <com/sun/star/io/XConnectable.hpp>
+
+#include <unotools/ucbstreamhelper.hxx>
+#include <tools/stream.hxx>
+
+namespace dbahsql
+{
+using namespace css::uno;
+using namespace css::sdbc;
+using namespace css::io;
+
+typedef std::vector<sal_Int32> ColumnTypeVector;
+
+HsqlRowInputStream::HsqlRowInputStream() {}
+
+void HsqlRowInputStream::setInputStream(Reference<XInputStream>& rStream)
+{
+    m_pStream.reset(utl::UcbStreamHelper::CreateStream(rStream, true));
+    m_pStream->SetEndian(SvStreamEndian::BIG);
+}
+
+SvStream* HsqlRowInputStream::getInputStream() const { return m_pStream.get(); }
+
+void HsqlRowInputStream::seek(sal_Int32 nPos) { m_pStream->Seek(nPos); }
+
+OUString HsqlRowInputStream::readString()
+{
+    sal_Int32 nLen = 0;
+    m_pStream->ReadInt32(nLen);
+    return readUTF(nLen);
+}
+
+OUString HsqlRowInputStream::readUTF(sal_Int32 nUTFLen)
+{
+    Sequence<sal_Unicode> aBuffer(nUTFLen);
+    sal_Unicode* pStr = aBuffer.getArray();
+
+    sal_Int32 nCount = 0;
+    sal_Int32 nStrLen = 0;
+    while (nCount < nUTFLen)
+    {
+        unsigned char cIn = 0;
+        m_pStream->ReadUChar(cIn);
+        sal_uInt8 c = reinterpret_cast<sal_uInt8&>(cIn);
+        sal_uInt8 char2, char3;
+        switch (c >> 4)
+        {
+            case 0:
+            case 1:
+            case 2:
+            case 3:
+            case 4:
+            case 5:
+            case 6:
+            case 7:
+                // 0xxxxxxx
+                nCount++;
+                pStr[nStrLen++] = c;
+                break;
+
+            case 12:
+            case 13:
+                // 110x xxxx   10xx xxxx
+                nCount += 2;
+                if (nCount > nUTFLen)
+                {
+                    throw WrongFormatException();
+                }
+
+                m_pStream->ReadUChar(cIn);
+                char2 = reinterpret_cast<sal_uInt8&>(cIn);
+                if ((char2 & 0xC0) != 0x80)
+                {
+                    throw WrongFormatException();
+                }
+
+                pStr[nStrLen++] = (sal_Unicode(c & 0x1F) << 6) | (char2 & 0x3F);
+                break;
+
+            case 14:
+                // 1110 xxxx  10xx xxxx  10xx xxxx
+                nCount += 3;
+                if (nCount > nUTFLen)
+                {
+                    throw WrongFormatException();
+                }
+
+                m_pStream->ReadUChar(cIn);
+                char2 = reinterpret_cast<sal_uInt8&>(cIn);
+                m_pStream->ReadUChar(cIn);
+                char3 = reinterpret_cast<sal_uInt8&>(cIn);
+
+                if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
+                {
+                    throw WrongFormatException();
+                }
+                pStr[nStrLen++] = (sal_Unicode(c & 0x0F) << 12) | (sal_Unicode(char2 & 0x3F) << 6)
+                                  | (char3 & 0x3F);
+                break;
+
+            default:
+                // 10xx xxxx,  1111 xxxx
+                throw WrongFormatException();
+        }
+    }
+    return OUString(pStr, nStrLen);
+}
+
+bool HsqlRowInputStream::checkNull()
+{
+    unsigned char cIn = 0;
+    m_pStream->ReadUChar(cIn);
+    sal_uInt8 nNull = reinterpret_cast<sal_uInt8&>(cIn);
+    return nNull == 0;
+}
+
+std::vector<Any> HsqlRowInputStream::readOneRow(const ColumnTypeVector& nColTypes)
+{
+    auto nLen = nColTypes.size();
+    std::vector<Any> aData;
+
+    for (size_t i = 0; i < nLen; ++i)
+    {
+        if (checkNull())
+        {
+            aData.push_back(Any());
+            continue;
+        }
+
+        sal_Int32 nType = nColTypes[i];
+
+        // TODO throw error on EoF
+
+        switch (nType)
+        {
+            case DataType::CHAR:
+            case DataType::VARCHAR:
+            case DataType::LONGVARCHAR:
+                aData.push_back(makeAny(readString()));
+                break;
+            case DataType::TINYINT:
+            case DataType::SMALLINT:
+            {
+                sal_Int16 value = 0;
+                m_pStream->ReadInt16(value);
+                aData.push_back(makeAny(value));
+            }
+            break;
+            case DataType::INTEGER:
+            {
+                sal_Int32 value = 0;
+                m_pStream->ReadInt32(value);
+                aData.push_back(makeAny(value));
+            }
+            break;
+            case DataType::BIGINT:
+            {
+                sal_Int64 value = 0;
+                m_pStream->ReadInt64(value);
+                aData.push_back(makeAny(value));
+            }
+            break;
+            case DataType::REAL:
+            case DataType::FLOAT:
+            case DataType::DOUBLE:
+            {
+                double value = 0;
+                m_pStream->ReadDouble(value);
+                // FIXME double is not necessarily 4 bytes
+                aData.push_back(makeAny(value));
+            }
+            break;
+            case DataType::NUMERIC:
+            case DataType::DECIMAL:
+            {
+                sal_Int32 nSize = 0;
+                m_pStream->ReadInt32(nSize);
+
+                std::vector<sal_uInt8> aBytes(nSize);
+                m_pStream->ReadBytes(aBytes.data(), nSize);
+
+                // TODO make a numeric out of this.
+            }
+            break;
+            case DataType::DATE:
+                break;
+            case DataType::TIME:
+                break;
+            case DataType::TIMESTAMP:
+                break;
+            case DataType::BOOLEAN:
+            {
+                sal_uInt8 nBool = 0;
+                m_pStream->ReadUChar(nBool);
+                aData.push_back(makeAny(static_cast<bool>(nBool)));
+            }
+            break;
+            case DataType::OTHER:
+                // TODO
+                break;
+            case DataType::BINARY:
+            case DataType::VARBINARY:
+            case DataType::LONGVARBINARY:
+            {
+                sal_Int32 nSize = 0;
+                m_pStream->ReadInt32(nSize);
+
+                Sequence<sal_uInt8> aBytes(nSize);
+                m_pStream->ReadBytes(aBytes.getArray(), nSize);
+                aData.push_back(makeAny(aBytes));
+            }
+            break;
+
+            default:
+                // TODO other exception
+                throw WrongFormatException();
+        }
+    }
+    return aData;
+}
+
+} // namespace dbahsql
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/rowinputbinary.hxx b/dbaccess/source/filter/hsqldb/rowinputbinary.hxx
new file mode 100644
index 000000000000..e2e56944c55b
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/rowinputbinary.hxx
@@ -0,0 +1,46 @@
+/* -*- 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/.
+ */
+
+#ifndef INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_ROWINPUTBINARY_HXX
+#define INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_ROWINPUTBINARY_HXX
+
+#include <vector>
+#include <tools/stream.hxx>
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/io/XInputStream.hpp>
+#include <tools/stream.hxx>
+
+namespace dbahsql
+{
+class HsqlRowInputStream
+{
+private:
+    std::unique_ptr<SvStream> m_pStream = nullptr;
+
+protected:
+    OUString readString();
+    bool checkNull();
+
+    // reimplement reading of an UTF string with a given length
+    OUString readUTF(sal_Int32 nLen);
+
+public:
+    HsqlRowInputStream();
+    std::vector<css::uno::Any> readOneRow(const std::vector<sal_Int32>& colTypes);
+    void seek(sal_Int32 nPos);
+    void setInputStream(css::uno::Reference<css::io::XInputStream>& rStream);
+    SvStream* getInputStream() const;
+};
+
+} // namespace dbahsql
+
+#endif // INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_ROWINPUTBINARY_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list