diff options
Diffstat (limited to 'dbaccess/source/filter/hsqldb/createparser.cxx')
-rw-r--r-- | dbaccess/source/filter/hsqldb/createparser.cxx | 223 |
1 files changed, 223 insertions, 0 deletions
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 <comphelper/string.hxx> +#include "createparser.hxx" +#include <com/sun/star/sdbc/DataType.hpp> + +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<OUString> lcl_splitColumnPart(const OUString& sColumnPart) +{ + std::vector<OUString> sParts = string::split(sColumnPart, sal_Unicode(u',')); + std::vector<OUString> 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<OUString> 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<sal_Int32> 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: */ |