From 95bece38ac5c943657ad959cad148c84a91d45a4 Mon Sep 17 00:00:00 2001 From: Tamas Bunth Date: Mon, 8 Jan 2018 15:57:39 +0100 Subject: Add HSQLDB schema import MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It can be enabled by initializing the DBACCESS_HSQL_MIGRATION variable. Create new library "dbahsql" which is responsible for migrating the embedded hsql database to any database covered by sdbc. The hsqldb schema is stored in a file named "script" in form of SQL statements. The SQL statements used by DBMS's differ mostly by the defined types. Because of that, only the create statements need to be parsed, alter statements will work (with a little luck) without actually modifying it. User / security settings which can occur in the script file (e.g. GRANT statements) are dropped. Statements starting with SET are also dropped (they are hsql specific stuff) Change-Id: I6a22942e8a9a76765f80e50f0ad68f4d72e1ff9d Reviewed-on: https://gerrit.libreoffice.org/48260 Tested-by: Jenkins Reviewed-by: Tamás Bunth --- Repository.mk | 3 +- .../source/drivers/firebird/Connection.cxx | 8 +- dbaccess/Library_dba.mk | 2 + dbaccess/Library_dbahsql.mk | 40 ++++ dbaccess/Module_dbaccess.mk | 1 + dbaccess/README.vars | 1 + dbaccess/inc/pch/precompiled_dbahsql.cxx | 12 ++ dbaccess/inc/pch/precompiled_dbahsql.hxx | 38 ++++ dbaccess/source/core/dataaccess/datasource.cxx | 26 +++ dbaccess/source/filter/hsqldb/columndef.cxx | 41 ++++ dbaccess/source/filter/hsqldb/columndef.hxx | 59 ++++++ dbaccess/source/filter/hsqldb/createparser.cxx | 223 +++++++++++++++++++++ dbaccess/source/filter/hsqldb/createparser.hxx | 51 +++++ dbaccess/source/filter/hsqldb/fbcreateparser.cxx | 163 +++++++++++++++ dbaccess/source/filter/hsqldb/fbcreateparser.hxx | 38 ++++ dbaccess/source/filter/hsqldb/hsqlimport.cxx | 56 ++++++ dbaccess/source/filter/hsqldb/hsqlimport.hxx | 47 +++++ dbaccess/source/filter/hsqldb/parseschema.cxx | 82 ++++++++ dbaccess/source/filter/hsqldb/parseschema.hxx | 44 ++++ 19 files changed, 929 insertions(+), 6 deletions(-) create mode 100644 dbaccess/Library_dbahsql.mk create mode 100644 dbaccess/README.vars create mode 100644 dbaccess/inc/pch/precompiled_dbahsql.cxx create mode 100644 dbaccess/inc/pch/precompiled_dbahsql.hxx create mode 100644 dbaccess/source/filter/hsqldb/columndef.cxx create mode 100644 dbaccess/source/filter/hsqldb/columndef.hxx create mode 100644 dbaccess/source/filter/hsqldb/createparser.cxx create mode 100644 dbaccess/source/filter/hsqldb/createparser.hxx create mode 100644 dbaccess/source/filter/hsqldb/fbcreateparser.cxx create mode 100644 dbaccess/source/filter/hsqldb/fbcreateparser.hxx create mode 100644 dbaccess/source/filter/hsqldb/hsqlimport.cxx create mode 100644 dbaccess/source/filter/hsqldb/hsqlimport.hxx create mode 100644 dbaccess/source/filter/hsqldb/parseschema.cxx create mode 100644 dbaccess/source/filter/hsqldb/parseschema.hxx diff --git a/Repository.mk b/Repository.mk index aa67702d1ce0..f209195ed88d 100644 --- a/Repository.mk +++ b/Repository.mk @@ -353,7 +353,8 @@ $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,ooo, \ dba \ dbase \ dbmm \ - dbaxml) \ + dbaxml \ + dbahsql) \ dbtools \ deploymentmisc \ $(if $(filter-out MACOSX WNT,$(OS)),desktopbe1) \ diff --git a/connectivity/source/drivers/firebird/Connection.cxx b/connectivity/source/drivers/firebird/Connection.cxx index 5316895c3679..619f324720e9 100644 --- a/connectivity/source/drivers/firebird/Connection.cxx +++ b/connectivity/source/drivers/firebird/Connection.cxx @@ -205,11 +205,9 @@ void Connection::construct(const ::rtl::OUString& url, const Sequence< PropertyV } else { - ::connectivity::SharedResources aResources; - // TODO FIXME: this does _not_ look like the right error message - const OUString sMessage = aResources.getResourceString(STR_ERROR_NEW_VERSION); - ::dbtools::throwGenericSQLException(sMessage ,*this); - + // There might be files which are not firebird databases. + // This is not a problem. + bIsNewDatabase = true; } } // TODO: Get DB properties from XML diff --git a/dbaccess/Library_dba.mk b/dbaccess/Library_dba.mk index 9af43f75c3de..52eae77d8d78 100644 --- a/dbaccess/Library_dba.mk +++ b/dbaccess/Library_dba.mk @@ -14,6 +14,7 @@ $(eval $(call gb_Library_set_include,dba,\ -I$(SRCDIR)/dbaccess/inc \ -I$(SRCDIR)/dbaccess/source/inc \ -I$(SRCDIR)/dbaccess/source/core/inc \ + -I$(SRCDIR)/dbaccess/source/filter/hsqldb \ -I$(WORKDIR)/YaccTarget/connectivity/source/parse \ )) @@ -31,6 +32,7 @@ $(eval $(call gb_Library_use_libraries,dba,\ comphelper \ cppu \ cppuhelper \ + dbahsql \ dbtools \ fwe \ i18nlangtag \ diff --git a/dbaccess/Library_dbahsql.mk b/dbaccess/Library_dbahsql.mk new file mode 100644 index 000000000000..f85660e6b3a8 --- /dev/null +++ b/dbaccess/Library_dbahsql.mk @@ -0,0 +1,40 @@ +# -*- 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_Library_Library,dbahsql)) + +$(eval $(call gb_Library_set_include,dbahsql,\ + $$(INCLUDE) \ + -I$(WORKDIR)/YaccTarget/connectivity/source/parse \ +)) + +$(eval $(call gb_Library_use_external,dbahsql,boost_headers)) + +$(eval $(call gb_Library_set_precompiled_header,dbahsql,$(SRCDIR)/dbaccess/inc/pch/precompiled_dbahsql)) + +$(eval $(call gb_Library_use_sdk_api,dbahsql)) + +$(eval $(call gb_Library_use_libraries,dbahsql,\ + comphelper \ + cppu \ + cppuhelper \ + sal \ + salhelper \ + dbtools \ +)) + +$(eval $(call gb_Library_add_exception_objects,dbahsql,\ + dbaccess/source/filter/hsqldb/hsqlimport \ + dbaccess/source/filter/hsqldb/parseschema \ + dbaccess/source/filter/hsqldb/createparser \ + dbaccess/source/filter/hsqldb/columndef \ + dbaccess/source/filter/hsqldb/fbcreateparser \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/dbaccess/Module_dbaccess.mk b/dbaccess/Module_dbaccess.mk index 4a0a6d9bf9dc..9bc2253f7465 100644 --- a/dbaccess/Module_dbaccess.mk +++ b/dbaccess/Module_dbaccess.mk @@ -18,6 +18,7 @@ $(eval $(call gb_Module_add_targets,dbaccess,\ Library_dbmm \ Library_dbu \ Library_sdbt \ + Library_dbahsql \ UIConfig_dbaccess \ UIConfig_dbapp \ UIConfig_dbbrowser \ diff --git a/dbaccess/README.vars b/dbaccess/README.vars new file mode 100644 index 000000000000..2614dbcc4100 --- /dev/null +++ b/dbaccess/README.vars @@ -0,0 +1 @@ +DBACCESS_HSQL_MIGRATION: Migrate embedded HSQLDB database diff --git a/dbaccess/inc/pch/precompiled_dbahsql.cxx b/dbaccess/inc/pch/precompiled_dbahsql.cxx new file mode 100644 index 000000000000..b56d7b2322ab --- /dev/null +++ b/dbaccess/inc/pch/precompiled_dbahsql.cxx @@ -0,0 +1,12 @@ +/* -*- 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 "precompiled_dbahsql.hxx" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/inc/pch/precompiled_dbahsql.hxx b/dbaccess/inc/pch/precompiled_dbahsql.hxx new file mode 100644 index 000000000000..8422b7dd8fdd --- /dev/null +++ b/dbaccess/inc/pch/precompiled_dbahsql.hxx @@ -0,0 +1,38 @@ +/* -*- 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 has been autogenerated by update_pch.sh. It is possible to edit it + manually (such as when an include file has been moved/renamed/removed). All such + manual changes will be rewritten by the next run of update_pch.sh (which presumably + also fixes all possible problems, so it's usually better to use it). + + Generated on 2018-01-22 10:22:30 using: + bin/update_pch dbaccess dbahsql --cutoff=2 --exclude:system --exclude:module --exclude:local + + If after updating build fails, use the following command to locate conflicting headers: + ./bin/update_pch_bisect ./dbaccess/inc/pch/precompiled_dbahsql.hxx "make dbaccess.build" --find-conflicts +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/core/dataaccess/datasource.cxx b/dbaccess/source/core/dataaccess/datasource.cxx index 059a8f67a410..cab756146286 100644 --- a/dbaccess/source/core/dataaccess/datasource.cxx +++ b/dbaccess/source/core/dataaccess/datasource.cxx @@ -28,6 +28,8 @@ #include "databasedocument.hxx" #include +#include + #include #include #include @@ -61,6 +63,7 @@ #include #include #include +#include #include #include #include @@ -595,6 +598,7 @@ Reference< XConnection > ODatabaseSource::buildLowLevelConnection(const OUString } const char* pExceptionMessageId = RID_STR_COULDNOTCONNECT_UNSPECIFIED; + bool bNeedMigration = false; if (xManager.is()) { sal_Int32 nAdditionalArgs(0); @@ -617,6 +621,19 @@ Reference< XConnection > ODatabaseSource::buildLowLevelConnection(const OUString Reference< XDriver > xDriver; try { + // check if migration is needed + OUString sMigrEnvValue; + osl_getEnvironment(OUString("DBACCESS_HSQL_MIGRATION").pData, + &sMigrEnvValue.pData); + if( m_pImpl->m_sConnectURL == "sdbc:embedded:hsqldb" && + !sMigrEnvValue.isEmpty() ) + { + // TODO target could be anything else + m_pImpl->m_sConnectURL = "sdbc:embedded:firebird"; + bNeedMigration = true; + } + + // choose driver Reference< XDriverAccess > xAccessDrivers( xManager, UNO_QUERY ); if ( xAccessDrivers.is() ) xDriver = xAccessDrivers->getDriverByURL( m_pImpl->m_sConnectURL ); @@ -686,6 +703,15 @@ Reference< XConnection > ODatabaseSource::buildLowLevelConnection(const OUString throwGenericSQLException( sMessage, static_cast< XDataSource* >( this ), makeAny( aContext ) ); } + if( bNeedMigration ) + { + Reference< css::document::XDocumentSubStorageSupplier> xDocSup( + m_pImpl->getDocumentSubStorageSupplier() ); + dbahsql::HsqlImporter importer(xReturn, + xDocSup->getDocumentSubStorage("database",ElementModes::READWRITE) ); + importer.importHsqlDatabase(); + } + return xReturn; } diff --git a/dbaccess/source/filter/hsqldb/columndef.cxx b/dbaccess/source/filter/hsqldb/columndef.cxx new file mode 100644 index 000000000000..8cdd53f1ba49 --- /dev/null +++ b/dbaccess/source/filter/hsqldb/columndef.cxx @@ -0,0 +1,41 @@ + +/* -*- 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 "columndef.hxx" +#include + +namespace dbahsql +{ +using namespace css::sdbc; + +ColumnDefinition::ColumnDefinition(const OUString& sName, sal_Int32 eType, + const std::vector aParams, bool bPrimary, + sal_Int32 nAutoIncr, bool bNullable) + : m_sName(sName) + , m_eType(eType) + , m_aParams(aParams) + , m_bPrimaryKey(bPrimary) + , m_nAutoIncrement(nAutoIncr) + , m_bNullable(bNullable) +{ +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/filter/hsqldb/columndef.hxx b/dbaccess/source/filter/hsqldb/columndef.hxx new file mode 100644 index 000000000000..4c46ac10a5ce --- /dev/null +++ b/dbaccess/source/filter/hsqldb/columndef.hxx @@ -0,0 +1,59 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_COLUMNDEF_HXX +#define INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_COLUMNDEF_HXX + +#include +#include + +namespace dbahsql +{ +/// nAutoIncrement: column is auto incremented started with value nAutoIncrement +class ColumnDefinition +{ +private: + OUString m_sName; + sal_Int32 m_eType; // css::sdbc::DataType + std::vector m_aParams; + bool m_bPrimaryKey; + sal_Int32 m_nAutoIncrement; + bool m_bNullable; + +public: + ColumnDefinition(const OUString& sName, sal_Int32 eType, const std::vector aParams, + bool bPrimary = false, sal_Int32 nAutoIncr = -1, bool bNullable = true); + + OUString getName() const { return m_sName; } + sal_Int32 getDataType() const { return m_eType; } + bool isPrimaryKey() const { return m_bPrimaryKey; } + bool isNullable() const { return m_bNullable; } + sal_Int32 getAutoIncrementDefault() const + { + assert(m_nAutoIncrement > 0); + return m_nAutoIncrement; + } + bool isAutoIncremental() const { return m_nAutoIncrement >= 0; } + const std::vector getParams() const { return m_aParams; } +}; +} + +#endif // INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_COLUMNDEF_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/filter/hsqldb/createparser.cxx b/dbaccess/source/filter/hsqldb/createparser.cxx new file mode 100644 index 000000000000..4df5a097bc64 --- /dev/null +++ b/dbaccess/source/filter/hsqldb/createparser.cxx @@ -0,0 +1,223 @@ +/* -*- 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 +#include "createparser.hxx" +#include + +using namespace ::comphelper; +using namespace css::sdbc; + +namespace +{ +OUString lcl_getTableName(const OUString& sSql) +{ + auto stmtComponents = string::split(sSql, sal_Unicode(u' ')); + assert(stmtComponents.size() > 2); + auto wordIter = stmtComponents.begin(); + + if (*wordIter == "CREATE") + ++wordIter; + if (*wordIter == "CACHED") + ++wordIter; + if (*wordIter == "TABLE") + ++wordIter; + + // next word is the table's name + // it might stuck together with the column definitions. + sal_Int32 nParenPos = wordIter->indexOf("("); + if (nParenPos > 0) + return wordIter->copy(0, nParenPos); + else + return *wordIter; +} + +/// Returns substring of sSql from the first occurrence of '(' until the +/// last occurrence of ')' (excluding the parenthesis) +OUString lcl_getColumnPart(const OUString& sSql) +{ + sal_Int32 nBeginIndex = sSql.indexOf("(") + 1; + if (nBeginIndex < 0) + { + SAL_WARN("dbaccess", "No column definitions found"); + return OUString(); + } + sal_Int32 nCount = sSql.lastIndexOf(")") - nBeginIndex; + return sSql.copy(nBeginIndex, nCount); +} + +/// Constructs a vector of strings that represents the definitions of each +/// column or constraint. +/// +/// @param sColumnPart part of the create statement inside the parenthesis +/// containing the column definitions +std::vector lcl_splitColumnPart(const OUString& sColumnPart) +{ + std::vector sParts = string::split(sColumnPart, sal_Unicode(u',')); + std::vector sReturn; + + OUStringBuffer current; + for (auto it = sParts.begin(); it != sParts.end(); ++it) + { + current.append(*it); + if (current.lastIndexOf("(") > current.lastIndexOf(")")) + current.append(","); // it was false split + else + sReturn.push_back(current.makeStringAndClear()); + } + return sReturn; +} + +sal_Int32 lcl_getAutoIncrementDefault(const OUString& sColumnDef) +{ + // TODO what if there are more spaces? + if (sColumnDef.indexOf("GENERATED BY DEFAULT AS IDENTITY") > 0) + { + // TODO parse starting sequence stated by "START WITH" + return 0; + } + return -1; +} + +bool lcl_isNullable(const OUString& sColumnDef) +{ + if (sColumnDef.indexOf("NOT NULL") >= 0) + { + return false; + } + return true; +} + +bool lcl_isPrimaryKey(const OUString& sColumnDef) +{ + if (sColumnDef.indexOf("PRIMARY KEY") >= 0) + { + return true; + } + return false; +} + +sal_Int32 lcl_getDataTypeFromHsql(const OUString& sTypeName) +{ + if (sTypeName == "CHAR") + return DataType::CHAR; + else if (sTypeName == "VARCHAR") + return DataType::VARCHAR; + else if (sTypeName == "TINYINT") + return DataType::TINYINT; + else if (sTypeName == "SMALLINT") + return DataType::SMALLINT; + else if (sTypeName == "INTEGER") + return DataType::INTEGER; + else if (sTypeName == "BIGINT") + return DataType::BIGINT; + else if (sTypeName == "NUMERIC") + return DataType::NUMERIC; + else if (sTypeName == "DECIMAL") + return DataType::DECIMAL; + else if (sTypeName == "BOOLEAN") + return DataType::BOOLEAN; + else if (sTypeName == "LONGVARCHAR") + return DataType::LONGVARCHAR; + else if (sTypeName == "LONGVARBINARY") + return DataType::LONGVARBINARY; + else if (sTypeName == "CLOB") + return DataType::CLOB; + else if (sTypeName == "BLOB") + return DataType::BLOB; + else if (sTypeName == "BINARY") + return DataType::BINARY; + else if (sTypeName == "VARBINARY") + return DataType::VARBINARY; + else if (sTypeName == "DATE") + return DataType::DATE; + else if (sTypeName == "TIME") + return DataType::TIME; + else if (sTypeName == "TIMESTAMP") + return DataType::TIMESTAMP; + else if (sTypeName == "DOUBLE") + return DataType::DOUBLE; + + assert(false); + return -1; +} +} + +namespace dbahsql +{ +CreateStmtParser::CreateStmtParser() {} + +void CreateStmtParser::parseColumnPart(const OUString& sColumnPart) +{ + auto sColumns = lcl_splitColumnPart(sColumnPart); + for (OUString& sColumn : sColumns) + { + std::vector words = string::split(sColumn, sal_Unicode(u' ')); + + if (words[0] == "CONSTRAINT") + { + // TODO parse foreign key part instead of just saving the string + // part + m_aForeignParts.push_back(sColumn); + continue; + } + + std::vector aParams; + OUString sTypeName = words[1]; + + // TODO what if there is a whitespace between type name and param? + sal_Int32 nParenPos = words[1].indexOf("("); + if (nParenPos > 0) + { + sTypeName = words[1].copy(0, nParenPos); + + OUString sParamStr + = words[1].copy(nParenPos + 1, words[1].lastIndexOf(")") - nParenPos - 1); + auto sParams = string::split(sParamStr, sal_Unicode(u',')); + for (auto& sParam : sParams) + { + aParams.push_back(sParam.toInt32()); + } + } + + ColumnDefinition aColDef(words[0], lcl_getDataTypeFromHsql(sTypeName), aParams, + lcl_isPrimaryKey(sColumn), lcl_getAutoIncrementDefault(sColumn), + lcl_isNullable(sColumn)); + + m_aColumns.push_back(aColDef); + } +} + +void CreateStmtParser::parse(const OUString& sSql) +{ + // TODO Foreign keys + if (!sSql.startsWith("CREATE")) + { + SAL_WARN("dbaccess", "Not a create statement"); + return; + } + + m_sTableName = lcl_getTableName(sSql); + OUString sColumnPart = lcl_getColumnPart(sSql); + parseColumnPart(sColumnPart); +} + +} // namespace dbahsql + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/filter/hsqldb/createparser.hxx b/dbaccess/source/filter/hsqldb/createparser.hxx new file mode 100644 index 000000000000..4bc4bd2343b6 --- /dev/null +++ b/dbaccess/source/filter/hsqldb/createparser.hxx @@ -0,0 +1,51 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_CREATEPARSER_HXX +#define INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_CREATEPARSER_HXX + +#include +#include "columndef.hxx" + +namespace dbahsql +{ +class CreateStmtParser +{ +private: + std::vector m_aColumns; + std::vector m_aForeignParts; + OUString m_sTableName; + +protected: + void parseColumnPart(const OUString& sColumnPart); + +public: + CreateStmtParser(); + virtual ~CreateStmtParser() {} + OUString getTableName() const { return m_sTableName; } + const std::vector& getColumnDef() const { return m_aColumns; } + const std::vector& getForeignParts() const { return m_aForeignParts; } + void parse(const OUString& sSql); + virtual OUString compose() const = 0; +}; +} + +#endif // INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_CREATEPARSER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/filter/hsqldb/fbcreateparser.cxx b/dbaccess/source/filter/hsqldb/fbcreateparser.cxx new file mode 100644 index 000000000000..f69580423cf2 --- /dev/null +++ b/dbaccess/source/filter/hsqldb/fbcreateparser.cxx @@ -0,0 +1,163 @@ +/* -*- 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 "fbcreateparser.hxx" +#include "columndef.hxx" + +#include +#include + +using namespace css::sdbc; + +namespace +{ +void lcl_appendWithSpace(OUStringBuffer& sBuff, const OUString& sStr) +{ + sBuff.append(" "); + sBuff.append(sStr); +} + +OUString lcl_DataTypetoFbTypeName(sal_Int32 eType) +{ + switch (eType) + { + case DataType::CHAR: + case DataType::BINARY: + return OUString("CHAR"); + case DataType::VARCHAR: + case DataType::VARBINARY: + return OUString("VARCHAR"); + case DataType::TINYINT: // no such type in Firebird + case DataType::SMALLINT: + return OUString("SMALLINT"); + case DataType::INTEGER: + return OUString("INTEGER"); + case DataType::BIGINT: + return OUString("BIGINT"); + case DataType::NUMERIC: + return OUString("NUMERIC"); + case DataType::DECIMAL: + return OUString("DECIMAL"); + case DataType::BOOLEAN: + return OUString("BOOLEAN"); + case DataType::LONGVARCHAR: + case DataType::LONGVARBINARY: + case DataType::CLOB: + case DataType::BLOB: + case DataType::OTHER: + return OUString("BLOB"); + case DataType::DATE: + return OUString("DATE"); + case DataType::TIME: + return OUString("TIME"); + case DataType::TIMESTAMP: + return OUString("TIMESTAMP"); + case DataType::DOUBLE: + return OUString("DOUBLE PRECISION"); + default: + assert(false); + return OUString(); + } +} + +OUString lcl_getTypeModifier(sal_Int32 eType) +{ + // TODO bind -9546 magic number to a common definition. It also appears + // in the connectivity modul. + switch (eType) + { + case DataType::CLOB: + case DataType::LONGVARCHAR: + return OUString("SUB_TYPE 1"); + case DataType::LONGVARBINARY: + return OUString("SUB_TYPE -9546"); + case DataType::BINARY: + case DataType::VARBINARY: + return OUString("CHARACTER SET OCTETS"); + default: + return OUString(); + } +} + +} // unnamed namespace + +namespace dbahsql +{ +OUString FbCreateStmtParser::compose() const +{ + OUStringBuffer sSql("CREATE TABLE "); + sSql.append(getTableName()); + + lcl_appendWithSpace(sSql, "("); + auto& rColumns = getColumnDef(); + auto columnIter = rColumns.cbegin(); + while (columnIter != rColumns.end()) + { + lcl_appendWithSpace(sSql, columnIter->getName()); + lcl_appendWithSpace(sSql, lcl_DataTypetoFbTypeName(columnIter->getDataType())); + + const std::vector params = columnIter->getParams(); + if (params.size() > 0) + { + sSql.append("("); + auto it = params.cbegin(); + while (it != params.end()) + { + sSql.append(OUString::number(*it)); + ++it; + if (it != params.end()) + sSql.append(","); + } + sSql.append(")"); // end of param declaration + } + + // special modifiers here, based on type (e.g. charset, subtype) + OUString sModifier = lcl_getTypeModifier(columnIter->getDataType()); + if (!sModifier.isEmpty()) + lcl_appendWithSpace(sSql, sModifier); + + // TODO autoincremental default value with "START WITH" + if (columnIter->isAutoIncremental()) + lcl_appendWithSpace(sSql, "GENERATED BY DEFAULT AS IDENTITY"); + else if (!columnIter->isNullable()) + lcl_appendWithSpace(sSql, "NOT NULL"); + + if (columnIter->isPrimaryKey()) + lcl_appendWithSpace(sSql, "PRIMARY KEY"); + + ++columnIter; + if (columnIter != rColumns.end()) + sSql.append(","); + } + + // foreign keys + const std::vector& sForeignParts = getForeignParts(); + for (const auto& sPart : sForeignParts) + { + sSql.append(","); + sSql.append(sPart); + } + + sSql.append(")"); // end of column declaration + return sSql.makeStringAndClear(); +} + +} // dbahsql + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/filter/hsqldb/fbcreateparser.hxx b/dbaccess/source/filter/hsqldb/fbcreateparser.hxx new file mode 100644 index 000000000000..02255089c1ca --- /dev/null +++ b/dbaccess/source/filter/hsqldb/fbcreateparser.hxx @@ -0,0 +1,38 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_FBCREATEPARSER_HXX +#define INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_FBCREATEPARSER_HXX + +#include "createparser.hxx" + +namespace dbahsql +{ +class FbCreateStmtParser : public CreateStmtParser +{ +public: + FbCreateStmtParser() {} + virtual OUString compose() const override; +}; + +} // dbahsql + +#endif // INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_FBCREATEPARSER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/filter/hsqldb/hsqlimport.cxx b/dbaccess/source/filter/hsqldb/hsqlimport.cxx new file mode 100644 index 000000000000..be0e1df4a538 --- /dev/null +++ b/dbaccess/source/filter/hsqldb/hsqlimport.cxx @@ -0,0 +1,56 @@ +/* -*- 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 +#include + +#include "hsqlimport.hxx" +#include "parseschema.hxx" + +namespace dbahsql +{ +using namespace css::uno; +using namespace css::sdbc; +using namespace css::embed; + +HsqlImporter::HsqlImporter(Reference& rConnection, const Reference& rStorage) + : m_rConnection(rConnection) + , m_xStorage(nullptr) +{ + m_xStorage.set(rStorage); +} + +void HsqlImporter::importSchema() +{ + assert(m_xStorage); + + SchemaParser parser(m_xStorage); + SqlStatementVector statements = parser.parseSchema(); + + for (auto& sSql : statements) + { + Reference 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 new file mode 100644 index 000000000000..d4887633e184 --- /dev/null +++ b/dbaccess/source/filter/hsqldb/hsqlimport.hxx @@ -0,0 +1,47 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_HSQLIMPORT_HXX +#define INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_HSQLIMPORT_HXX + +#include +#include + +namespace dbahsql +{ +class SAL_DLLPUBLIC_EXPORT HsqlImporter +{ +private: + css::uno::Reference& m_rConnection; + css::uno::Reference m_xStorage; + +protected: + void importSchema(); + +public: + HsqlImporter(css::uno::Reference& rConnection, + const css::uno::Reference& rStorage); + + void importHsqlDatabase(); +}; +} + +#endif // INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_HSQLIMPORT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/filter/hsqldb/parseschema.cxx b/dbaccess/source/filter/hsqldb/parseschema.cxx new file mode 100644 index 000000000000..a899fbba913e --- /dev/null +++ b/dbaccess/source/filter/hsqldb/parseschema.cxx @@ -0,0 +1,82 @@ +/* -*- 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 "parseschema.hxx" +#include "fbcreateparser.hxx" + +#include +#include +#include +#include + +namespace dbahsql +{ +using namespace css::io; +using namespace css::uno; +using namespace css::embed; + +SchemaParser::SchemaParser(Reference& rStorage) + : m_rStorage(rStorage) +{ +} + +SqlStatementVector SchemaParser::parseSchema() +{ + assert(m_rStorage); + + constexpr char SCHEMA_FILENAME[] = "script"; + if (!m_rStorage->hasByName(SCHEMA_FILENAME)) + { + SAL_WARN("dbaccess", "script file does not exist in storage during hsqldb import"); + assert(false); // TODO throw error + } + + Reference xStream(m_rStorage->openStreamElement(SCHEMA_FILENAME, ElementModes::READ)); + + Reference rContext = comphelper::getProcessComponentContext(); + Reference xTextInput = TextInputStream::create(rContext); + xTextInput->setEncoding("UTF-8"); + xTextInput->setInputStream(xStream->getInputStream()); + + SqlStatementVector parsedStatements; + while (!xTextInput->isEOF()) + { + // 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")) + continue; + + if (sSql.startsWith("CREATE CACHED TABLE") || sSql.startsWith("CREATE TABLE")) + { + FbCreateStmtParser aCreateParser; + aCreateParser.parse(sSql); + + sSql = aCreateParser.compose(); + } + + parsedStatements.push_back(sSql); + } + + return parsedStatements; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/dbaccess/source/filter/hsqldb/parseschema.hxx b/dbaccess/source/filter/hsqldb/parseschema.hxx new file mode 100644 index 000000000000..6767ce08414a --- /dev/null +++ b/dbaccess/source/filter/hsqldb/parseschema.hxx @@ -0,0 +1,44 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_PARSECHEMA_HXX +#define INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_PARSECHEMA_HXX + +#include +#include +#include + +namespace dbahsql +{ +typedef std::vector SqlStatementVector; + +class SchemaParser +{ +private: + css::uno::Reference& m_rStorage; + +public: + explicit SchemaParser(css::uno::Reference& rStorage); + SqlStatementVector parseSchema(); +}; +} + +#endif // INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_PARSESCHEMA_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3