From 4f043c0a269ff0bb13d4714dbcda471e47f7c1c1 Mon Sep 17 00:00:00 2001 From: Tamas Bunth Date: Mon, 14 May 2018 07:30:37 +0200 Subject: tdf#117092 dbahsql: handle multiple primary keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set primary keys at the end of the sql statement instead of putting it right after the column definition. This way multiple primary keys can be defined. Change-Id: I7956a536b0516fd8a773d4aa64ccb930ae5c715d Reviewed-on: https://gerrit.libreoffice.org/54204 Tested-by: Jenkins Reviewed-by: Tamás Bunth --- dbaccess/source/filter/hsqldb/createparser.cxx | 33 +++++++++++++++++++++--- dbaccess/source/filter/hsqldb/createparser.hxx | 7 +++++ dbaccess/source/filter/hsqldb/fbcreateparser.cxx | 17 ++++++++---- dbaccess/source/filter/hsqldb/parseschema.cxx | 6 +++++ dbaccess/source/filter/hsqldb/parseschema.hxx | 9 +++++++ 5 files changed, 63 insertions(+), 9 deletions(-) diff --git a/dbaccess/source/filter/hsqldb/createparser.cxx b/dbaccess/source/filter/hsqldb/createparser.cxx index 66993ace227b..1323d74e5ce7 100644 --- a/dbaccess/source/filter/hsqldb/createparser.cxx +++ b/dbaccess/source/filter/hsqldb/createparser.cxx @@ -154,17 +154,36 @@ namespace dbahsql { CreateStmtParser::CreateStmtParser() {} +void CreateStmtParser::parsePrimaryKeys(const OUString& sPrimaryPart) +{ + sal_Int32 nParenPos = sPrimaryPart.indexOf("("); + if (nParenPos > 0) + { + OUString sParamStr + = sPrimaryPart.copy(nParenPos + 1, sPrimaryPart.lastIndexOf(")") - nParenPos - 1); + auto sParams = string::split(sParamStr, sal_Unicode(u',')); + for (auto& sParam : sParams) + { + m_PrimaryKeys.push_back(sParam); + } + } +} + void CreateStmtParser::parseColumnPart(const OUString& sColumnPart) { auto sColumns = lcl_splitColumnPart(sColumnPart); for (OUString& sColumn : sColumns) { + if (sColumn.startsWithIgnoreAsciiCase("PRIMARY KEY")) + { + parsePrimaryKeys(sColumn); + continue; + } + 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; } @@ -192,8 +211,14 @@ void CreateStmtParser::parseColumnPart(const OUString& sColumnPart) } bool bCaseInsensitive = sTypeName.indexOf("IGNORECASE") >= 0; - ColumnDefinition aColDef(words[0], lcl_getDataTypeFromHsql(sTypeName), aParams, - lcl_isPrimaryKey(sColumn), lcl_getAutoIncrementDefault(sColumn), + const OUString& rTableName = words[0]; + bool isPrimaryKey = lcl_isPrimaryKey(sColumn); + + if (isPrimaryKey) + m_PrimaryKeys.push_back(rTableName); + + ColumnDefinition aColDef(rTableName, lcl_getDataTypeFromHsql(sTypeName), aParams, + isPrimaryKey, lcl_getAutoIncrementDefault(sColumn), lcl_isNullable(sColumn), bCaseInsensitive); m_aColumns.push_back(aColDef); diff --git a/dbaccess/source/filter/hsqldb/createparser.hxx b/dbaccess/source/filter/hsqldb/createparser.hxx index d23eef83b91b..41db73797c2e 100644 --- a/dbaccess/source/filter/hsqldb/createparser.hxx +++ b/dbaccess/source/filter/hsqldb/createparser.hxx @@ -20,10 +20,12 @@ class SAL_DLLPUBLIC_EXPORT CreateStmtParser private: std::vector m_aColumns; std::vector m_aForeignParts; + std::vector m_PrimaryKeys; OUString m_sTableName; protected: void parseColumnPart(const OUString& sColumnPart); + void parsePrimaryKeys(const OUString& sPrimaryPart); public: CreateStmtParser(); @@ -34,6 +36,11 @@ public: */ OUString getTableName() const { return m_sTableName; } + /** + * @return primary keys of parsed table. + */ + std::vector getPrimaryKeys() const { return m_PrimaryKeys; } + /** * @return a vector of column descriptors, representing the columns of the * parsed statement. diff --git a/dbaccess/source/filter/hsqldb/fbcreateparser.cxx b/dbaccess/source/filter/hsqldb/fbcreateparser.cxx index 8c36573ef9f8..d4f57c83800e 100644 --- a/dbaccess/source/filter/hsqldb/fbcreateparser.cxx +++ b/dbaccess/source/filter/hsqldb/fbcreateparser.cxx @@ -158,18 +158,25 @@ OUString FbCreateStmtParser::compose() const else if (!columnIter->isNullable()) lcl_appendWithSpace(sSql, "NOT NULL"); - if (columnIter->isPrimaryKey()) - lcl_appendWithSpace(sSql, "PRIMARY KEY"); - if (columnIter->isCaseInsensitive()) lcl_appendWithSpace(sSql, "COLLATE UNICODE_CI"); ++columnIter; - if (columnIter != rColumns.end()) + sSql.append(","); + } + + sSql.append("PRIMARY KEY("); + const std::vector& sPrimaryKeys = getPrimaryKeys(); + auto it = sPrimaryKeys.cbegin(); + while (it != sPrimaryKeys.end()) + { + sSql.append(*it); + ++it; + if (it != sPrimaryKeys.end()) sSql.append(","); } - sSql.append(")"); // end of column declaration + sSql.append("))"); // end of column declaration and primary keys return sSql.makeStringAndClear(); } diff --git a/dbaccess/source/filter/hsqldb/parseschema.cxx b/dbaccess/source/filter/hsqldb/parseschema.cxx index 25f26ed7e626..038793a797e5 100644 --- a/dbaccess/source/filter/hsqldb/parseschema.cxx +++ b/dbaccess/source/filter/hsqldb/parseschema.cxx @@ -147,6 +147,7 @@ void SchemaParser::parseSchema() // save column definitions m_ColumnTypes[aCreateParser.getTableName()] = aCreateParser.getColumnDef(); + m_sCreateStatements.push_back(sSql); } else if (sSql.startsWith("ALTER")) @@ -173,6 +174,11 @@ const std::map>& SchemaParser::getTableIndexes( return m_Indexes; } +const std::map>& SchemaParser::getPrimaryKeys() const +{ + return m_PrimaryKeys; +} + } // 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 a46e7ae4fdb6..0f69262a4227 100644 --- a/dbaccess/source/filter/hsqldb/parseschema.hxx +++ b/dbaccess/source/filter/hsqldb/parseschema.hxx @@ -32,6 +32,9 @@ private: // root element's position of data for each table std::map> m_Indexes; + // primary keys of each table + std::map> m_PrimaryKeys; + SqlStatementVector m_sCreateStatements; SqlStatementVector m_sAlterStatements; @@ -71,6 +74,12 @@ public: * contains one row. */ const std::map>& getTableIndexes() const; + + /** + * Returns a vector of column names for each table. These columns are the + * primary keys of the table. + */ + const std::map>& getPrimaryKeys() const; }; } -- cgit v1.2.3