LibreOffice Module dbaccess (master) 1
parseschema.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21
22#include <string_view>
23
24#include "parseschema.hxx"
25#include "fbcreateparser.hxx"
26#include "fbalterparser.hxx"
27#include "utils.hxx"
28
29#include <com/sun/star/io/TextInputStream.hpp>
30#include <com/sun/star/embed/XStorage.hpp>
31#include <com/sun/star/embed/ElementModes.hpp>
33#include <comphelper/string.hxx>
34#include <sal/log.hxx>
36#include <utility>
37
38namespace
39{
40using namespace ::comphelper;
41
42using IndexVector = std::vector<sal_Int32>;
43
44class IndexStmtParser
45{
46private:
47 OUString m_sql;
48
49public:
50 IndexStmtParser(OUString sSql)
51 : m_sql(std::move(sSql))
52 {
53 }
54
55 bool isIndexStatement() const
56 {
57 return m_sql.startsWith("SET TABLE") && m_sql.indexOf("INDEX") >= 0;
58 }
59
60 IndexVector getIndexes() const
61 {
62 assert(isIndexStatement());
63
64 std::u16string_view sIndexPart = m_sql.subView(m_sql.indexOf("INDEX") + 5);
65 size_t nQuotePos = sIndexPart.find('\'');
66 if (nQuotePos == std::u16string_view::npos)
67 nQuotePos = 0;
68 else
69 ++nQuotePos;
70 std::u16string_view sIndexNums
71 = sIndexPart.substr(nQuotePos, sIndexPart.rfind('\'') - nQuotePos);
72
73 std::vector<OUString> sIndexes = string::split(sIndexNums, u' ');
74 IndexVector indexes;
75 for (const auto& sIndex : sIndexes)
76 indexes.push_back(sIndex.toInt32());
77
78 // ignore last element
79 // TODO this is an identity peek, which indicates the value of the next
80 // identity. At the current state all migrated identities start with 0.
81 indexes.pop_back();
82
83 return indexes;
84 }
85
86 OUString getTableName() const
87 {
88 // SET TABLE <tableName> or SET TABLE "<multi word table name>"
89 OUString sName = string::split(m_sql, u' ')[2];
90 if (sName.indexOf('"') >= 0)
91 {
92 // Table name with string delimiter
93 sName = "\"" + string::split(m_sql, u'"')[1] + "\"";
94 }
95 return sName;
96 }
97};
98
99OUString lcl_createAlterForeign(std::u16string_view sForeignPart, std::u16string_view sTableName)
100{
101 return OUString::Concat("ALTER TABLE ") + sTableName + " ADD " + sForeignPart;
102}
103
104} // anonymous namespace
105
106namespace dbahsql
107{
108using namespace css::io;
109using namespace css::uno;
110using namespace css::embed;
111
112SchemaParser::SchemaParser(Reference<XStorage>& rStorage)
113 : m_rStorage(rStorage)
114{
115}
116
118{
119 assert(m_rStorage);
120
121 static constexpr OUStringLiteral SCHEMA_FILENAME = u"script";
122 if (!m_rStorage->hasByName(SCHEMA_FILENAME))
123 {
124 SAL_WARN("dbaccess", "script file does not exist in storage during hsqldb import");
125 return;
126 }
127
128 Reference<XStream> xStream(m_rStorage->openStreamElement(SCHEMA_FILENAME, ElementModes::READ));
129
130 Reference<XComponentContext> rContext = comphelper::getProcessComponentContext();
131 Reference<XTextInputStream2> xTextInput = TextInputStream::create(rContext);
132 xTextInput->setEncoding("UTF-8");
133 xTextInput->setInputStream(xStream->getInputStream());
134
135 while (!xTextInput->isEOF())
136 {
137 // every line contains exactly one DDL statement
138 OUString sSql = utils::convertToUTF8(
139 OUStringToOString(xTextInput->readLine(), RTL_TEXTENCODING_UTF8));
140
141 IndexStmtParser indexParser{ sSql };
142 if (indexParser.isIndexStatement())
143 {
144 m_Indexes[indexParser.getTableName()] = indexParser.getIndexes();
145 }
146 else if (sSql.startsWith("SET") || sSql.startsWith("CREATE USER")
147 || sSql.startsWith("CREATE SCHEMA") || sSql.startsWith("GRANT"))
148 continue;
149 else if (sSql.startsWith("CREATE CACHED TABLE") || sSql.startsWith("CREATE TABLE"))
150 {
151 FbCreateStmtParser aCreateParser;
152 aCreateParser.parse(sSql);
153
154 for (const auto& foreignParts : aCreateParser.getForeignParts())
155 {
156 m_sAlterStatements.push_back(
157 lcl_createAlterForeign(foreignParts, aCreateParser.getTableName()));
158 }
159
160 sSql = aCreateParser.compose();
161
162 // save column definitions
163 m_ColumnTypes[aCreateParser.getTableName()] = aCreateParser.getColumnDef();
164
165 m_sCreateStatements.push_back(sSql);
166 }
167 else if (sSql.startsWith("ALTER"))
168 {
169 FbAlterStmtParser aAlterParser;
170 aAlterParser.parse(sSql);
171 OUString parsedStmt = aAlterParser.compose();
172
173 if (!parsedStmt.isEmpty())
174 m_sAlterStatements.push_back(parsedStmt);
175 }
176 else if (sSql.startsWith("CREATE VIEW"))
177 m_sCreateStatements.push_back(sSql);
178 }
179}
180
181std::vector<ColumnDefinition> SchemaParser::getTableColumnTypes(const OUString& sTableName) const
182{
183 if (m_ColumnTypes.count(sTableName) < 1)
184 {
185 static constexpr OUStringLiteral NOT_EXIST
186 = u"Internal error while getting column information of table";
187 SAL_WARN("dbaccess", NOT_EXIST << ". Table name is: " << sTableName);
188 dbtools::throwGenericSQLException(NOT_EXIST, ::comphelper::getProcessComponentContext());
189 }
190 return m_ColumnTypes.at(sTableName);
191}
192
193const std::map<OUString, std::vector<sal_Int32>>& SchemaParser::getTableIndexes() const
194{
195 return m_Indexes;
196}
197
198const std::map<OUString, std::vector<OUString>>& SchemaParser::getPrimaryKeys() const
199{
200 return m_PrimaryKeys;
201}
202
203} // namespace dbahsql
204
205/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OptionalString sName
Reference< XInputStream > xStream
void parse(const OUString &sSql)
Definition: alterparser.cxx:27
const std::vector< OUString > & getForeignParts() const
void parse(std::u16string_view sSql)
Parses a create statement.
OUString const & getTableName() const
const std::vector< ColumnDefinition > & getColumnDef() const
virtual OUString compose() const override
Compose the result of the parser to statements of Firebird dialect.
virtual OUString compose() const override
Compose the result of the parser to statements of Firebird dialect.
std::map< OUString, std::vector< sal_Int32 > > m_Indexes
Definition: parseschema.hxx:31
SqlStatementVector m_sCreateStatements
Definition: parseschema.hxx:36
void parseSchema()
Parses table definitions contained by a file called "script" in storage.
const std::map< OUString, std::vector< OUString > > & getPrimaryKeys() const
Returns a vector of column names for each table.
std::map< OUString, std::vector< ColumnDefinition > > m_ColumnTypes
Definition: parseschema.hxx:28
std::vector< ColumnDefinition > getTableColumnTypes(const OUString &sTableName) const
Returns the column types of a table.
const std::map< OUString, std::vector< sal_Int32 > > & getTableIndexes() const
Returns a vector of indexes for each table.
SqlStatementVector m_sAlterStatements
Definition: parseschema.hxx:37
std::map< OUString, std::vector< OUString > > m_PrimaryKeys
Definition: parseschema.hxx:34
css::uno::Reference< css::embed::XStorage > & m_rStorage
Definition: parseschema.hxx:25
SchemaParser(css::uno::Reference< css::embed::XStorage > &rStorage)
float u
#define SAL_WARN(area, stream)
Reference< XComponentContext > getProcessComponentContext()
OUString convertToUTF8(std::string_view original)
Definition: utils.cxx:55
void throwGenericSQLException(const OUString &_rMsg, const css::uno::Reference< css::uno::XInterface > &_rxSource)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
SvStream & m_rStorage