diff options
-rw-r--r-- | dbaccess/Library_dbahsql.mk | 5 | ||||
-rw-r--r-- | dbaccess/source/filter/hsqldb/columndef.hxx | 10 | ||||
-rw-r--r-- | dbaccess/source/filter/hsqldb/createparser.hxx | 10 | ||||
-rw-r--r-- | dbaccess/source/filter/hsqldb/fbcreateparser.hxx | 10 | ||||
-rw-r--r-- | dbaccess/source/filter/hsqldb/hsqlbinarynode.cxx | 61 | ||||
-rw-r--r-- | dbaccess/source/filter/hsqldb/hsqlbinarynode.hxx | 39 | ||||
-rw-r--r-- | dbaccess/source/filter/hsqldb/hsqlimport.cxx | 241 | ||||
-rw-r--r-- | dbaccess/source/filter/hsqldb/hsqlimport.hxx | 20 | ||||
-rw-r--r-- | dbaccess/source/filter/hsqldb/parseschema.cxx | 26 | ||||
-rw-r--r-- | dbaccess/source/filter/hsqldb/parseschema.hxx | 17 | ||||
-rw-r--r-- | dbaccess/source/filter/hsqldb/rowinputbinary.cxx | 246 | ||||
-rw-r--r-- | dbaccess/source/filter/hsqldb/rowinputbinary.hxx | 46 |
12 files changed, 670 insertions, 61 deletions
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: */ |