summaryrefslogtreecommitdiff
path: root/dbaccess/source/filter/hsqldb/createparser.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'dbaccess/source/filter/hsqldb/createparser.cxx')
-rw-r--r--dbaccess/source/filter/hsqldb/createparser.cxx223
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: */