tdf#116982 dbahsql: fix autoincrementation

Fix autoincrementation issue by parsing and processing statements like
"ALTER TABLE <name> ALTER COLUMN <col_name> RESTART WITH <num>"

Change-Id: Ib175d64343d05d4b2cfc9a4cf944d0d0478adbcc
Reviewed-on: https://gerrit.libreoffice.org/52879
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Tamás Bunth <btomi96@gmail.com>
diff --git a/dbaccess/Library_dbahsql.mk b/dbaccess/Library_dbahsql.mk
index ec684b3..4932fae 100644
--- a/dbaccess/Library_dbahsql.mk
+++ b/dbaccess/Library_dbahsql.mk
@@ -38,11 +38,14 @@ $(eval $(call gb_Library_use_libraries,dbahsql,\
$(eval $(call gb_Library_add_exception_objects,dbahsql,\
    dbaccess/source/filter/hsqldb/hsqlimport \
    dbaccess/source/filter/hsqldb/parseschema \
    dbaccess/source/filter/hsqldb/alterparser \
    dbaccess/source/filter/hsqldb/createparser \
    dbaccess/source/filter/hsqldb/columndef \
    dbaccess/source/filter/hsqldb/fbalterparser \
    dbaccess/source/filter/hsqldb/fbcreateparser \
    dbaccess/source/filter/hsqldb/rowinputbinary \
    dbaccess/source/filter/hsqldb/hsqlbinarynode \
    dbaccess/source/filter/hsqldb/utils \
))

# vim: set noet sw=4 ts=4:
diff --git a/dbaccess/source/filter/hsqldb/alterparser.cxx b/dbaccess/source/filter/hsqldb/alterparser.cxx
new file mode 100644
index 0000000..f3c5323
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/alterparser.cxx
@@ -0,0 +1,48 @@
/* -*- 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 <comphelper/string.hxx>
#include "alterparser.hxx"
#include "utils.hxx"

namespace dbahsql
{
void AlterStmtParser::parse(const OUString& sSql)
{
    if (!sSql.startsWith("ALTER"))
    {
        SAL_WARN("dbaccess", "Not an ALTER statement");
        return;
    }

    m_sTableName = utils::getTableNameFromStmt(sSql);
    auto words = comphelper::string::split(sSql, sal_Unicode(u' '));

    if (words[3] == "ALTER" && words[4] == "COLUMN")
        m_sColumnName = words[5];
    if (words[6] == "RESTART" && words[7] == "WITH")
    {
        m_eAction = AlterAction::IDENTITY_RESTART;
        m_nIdentityParam = words[8].toInt32();
    }
}

} // namespace dbahsql

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/alterparser.hxx b/dbaccess/source/filter/hsqldb/alterparser.hxx
new file mode 100644
index 0000000..29d77b1
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/alterparser.hxx
@@ -0,0 +1,52 @@
/* -*- 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_ALTERPARSER_HXX
#define INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_ALTERPARSER_HXX

#include <rtl/ustrbuf.hxx>

namespace dbahsql
{
enum class AlterAction
{
    UNKNOWN,
    IDENTITY_RESTART
};

class SAL_DLLPUBLIC_EXPORT AlterStmtParser
{
private:
    OUString m_sTableName;
    OUString m_sColumnName;
    AlterAction m_eAction = AlterAction::UNKNOWN;
    sal_Int32 m_nIdentityParam = 0;

protected:
    AlterAction getActionType() const { return m_eAction; }
    OUString getColumnName() const { return m_sColumnName; }
    sal_Int32 getIdentityParam() const { return m_nIdentityParam; }

public:
    virtual ~AlterStmtParser() = default;

    /**
     * @return name of the table which is to be created.
     */
    OUString getTableName() const { return m_sTableName; }

    void parse(const OUString& sSql);

    virtual OUString compose() const = 0;
};
}

#endif // INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_ALTERPARSER_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/createparser.cxx b/dbaccess/source/filter/hsqldb/createparser.cxx
index bbc9bd7..8392964 100644
--- a/dbaccess/source/filter/hsqldb/createparser.cxx
+++ b/dbaccess/source/filter/hsqldb/createparser.cxx
@@ -19,6 +19,7 @@

#include <comphelper/string.hxx>
#include "createparser.hxx"
#include "utils.hxx"
#include <com/sun/star/sdbc/DataType.hpp>

using namespace ::comphelper;
@@ -26,28 +27,6 @@ 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)
@@ -225,7 +204,7 @@ void CreateStmtParser::parse(const OUString& sSql)
        return;
    }

    m_sTableName = lcl_getTableName(sSql);
    m_sTableName = utils::getTableNameFromStmt(sSql);
    OUString sColumnPart = lcl_getColumnPart(sSql);
    parseColumnPart(sColumnPart);
}
diff --git a/dbaccess/source/filter/hsqldb/fbalterparser.cxx b/dbaccess/source/filter/hsqldb/fbalterparser.cxx
new file mode 100644
index 0000000..ee34f4a
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/fbalterparser.cxx
@@ -0,0 +1,50 @@
/* -*- 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 "fbalterparser.hxx"
#include <rtl/ustrbuf.hxx>

namespace dbahsql
{
OUString FbAlterStmtParser::compose() const
{
    if (getActionType() == AlterAction::UNKNOWN)
    {
        SAL_WARN("dbaccess", "Unkown type of ALTER statement in FbAlterStmtParser");
        return OUString{};
    }
    OUStringBuffer sSql("ALTER TABLE ");
    sSql.append(getTableName());

    if (getActionType() == AlterAction::IDENTITY_RESTART)
    {
        sSql.append(" ALTER COLUMN ");
    }
    sSql.append(getColumnName());
    sSql.append(" RESTART WITH ");

    // Firebird: restart with 0 means the first number is 1, not 0.
    sSql.append(OUString::number(getIdentityParam() - 1));

    return sSql.makeStringAndClear();
}

} // dbahsql

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/fbalterparser.hxx b/dbaccess/source/filter/hsqldb/fbalterparser.hxx
new file mode 100644
index 0000000..99bbe55
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/fbalterparser.hxx
@@ -0,0 +1,30 @@
/* -*- 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_FBALTERPARSER_HXX
#define INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_FBALTERPARSER_HXX

#include "alterparser.hxx"

namespace dbahsql
{
class SAL_DLLPUBLIC_EXPORT FbAlterStmtParser : public AlterStmtParser
{
public:
    /**
     * Compose the result of the parser to statements of Firebird dialect
     */
    virtual OUString compose() const override;
};

} // dbahsql

#endif // INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_FBALTERPARSER_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/parseschema.cxx b/dbaccess/source/filter/hsqldb/parseschema.cxx
index 660b193..c9319b0 100644
--- a/dbaccess/source/filter/hsqldb/parseschema.cxx
+++ b/dbaccess/source/filter/hsqldb/parseschema.cxx
@@ -19,6 +19,7 @@

#include "parseschema.hxx"
#include "fbcreateparser.hxx"
#include "fbalterparser.hxx"

#include <com/sun/star/io/TextInputStream.hpp>
#include <com/sun/star/embed/XStorage.hpp>
@@ -133,6 +134,15 @@ SqlStatementVector SchemaParser::parseSchema()
            m_ColumnTypes[aCreateParser.getTableName()] = aCreateParser.getColumnDef();
            parsedStatements.push_back(sSql);
        }
        else if (sSql.startsWith("ALTER"))
        {
            FbAlterStmtParser aAlterParser;
            aAlterParser.parse(sSql);
            OUString parsedStmt = aAlterParser.compose();

            if (!parsedStmt.isEmpty())
                parsedStatements.push_back(parsedStmt);
        }
    }

    return parsedStatements;
diff --git a/dbaccess/source/filter/hsqldb/utils.cxx b/dbaccess/source/filter/hsqldb/utils.cxx
new file mode 100644
index 0000000..b6c5396
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/utils.cxx
@@ -0,0 +1,48 @@

/* -*- 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 <comphelper/string.hxx>
#include "utils.hxx"

using namespace dbahsql;

OUString utils::getTableNameFromStmt(const OUString& sSql)
{
    auto stmtComponents = comphelper::string::split(sSql, sal_Unicode(u' '));
    assert(stmtComponents.size() > 2);
    auto wordIter = stmtComponents.begin();

    if (*wordIter == "CREATE" || *wordIter == "ALTER")
        ++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;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/source/filter/hsqldb/utils.hxx b/dbaccess/source/filter/hsqldb/utils.hxx
new file mode 100644
index 0000000..cf76a1c
--- /dev/null
+++ b/dbaccess/source/filter/hsqldb/utils.hxx
@@ -0,0 +1,25 @@
/* -*- 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_UTILS_HXX
#define INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_UTILS_HXX

#include <rtl/ustring.hxx>

namespace dbahsql
{
namespace utils
{
OUString getTableNameFromStmt(const OUString& sSql);
}
}

#endif // INCLUDED_DBACCESS_SOURCE_FILTER_HSQLDB_UTILS_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */