bump product version to 7.2.5.1
[LibreOffice.git] / connectivity / source / drivers / mysql_jdbc / YTable.cxx
blob26e0fde19632e0b5a7c8e3645ddc884c88b51ebb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <mysql/YTable.hxx>
21 #include <mysql/YTables.hxx>
22 #include <cppuhelper/typeprovider.hxx>
23 #include <com/sun/star/beans/PropertyAttribute.hpp>
24 #include <com/sun/star/sdbcx/Privilege.hpp>
25 #include <comphelper/property.hxx>
26 #include <comphelper/servicehelper.hxx>
27 #include <comphelper/types.hxx>
28 #include <connectivity/dbtools.hxx>
29 #include <connectivity/sdbcx/VColumn.hxx>
30 #include <connectivity/TKeys.hxx>
31 #include <connectivity/TIndexes.hxx>
32 #include <mysql/YColumns.hxx>
33 #include <TConnection.hxx>
35 using namespace ::comphelper;
36 using namespace connectivity::mysql;
37 using namespace connectivity::sdbcx;
38 using namespace connectivity;
39 using namespace ::com::sun::star::uno;
40 using namespace ::com::sun::star::beans;
41 using namespace ::com::sun::star::sdbcx;
42 using namespace ::com::sun::star::sdbc;
43 using namespace ::com::sun::star::container;
44 using namespace ::com::sun::star::lang;
45 namespace connectivity::mysql
47 namespace
49 class OMySQLKeysHelper : public OKeysHelper
51 protected:
52 virtual OUString getDropForeignKey() const override { return " DROP FOREIGN KEY "; }
54 public:
55 OMySQLKeysHelper(OTableHelper* _pTable, ::osl::Mutex& _rMutex,
56 const ::std::vector<OUString>& _rVector)
57 : OKeysHelper(_pTable, _rMutex, _rVector)
64 OMySQLTable::OMySQLTable(sdbcx::OCollection* _pTables, const Reference<XConnection>& _xConnection)
65 : OTableHelper(_pTables, _xConnection, true)
67 // we create a new table here, so we should have all the rights or ;-)
68 m_nPrivileges = Privilege::DROP | Privilege::REFERENCE | Privilege::ALTER | Privilege::CREATE
69 | Privilege::READ | Privilege::DELETE | Privilege::UPDATE | Privilege::INSERT
70 | Privilege::SELECT;
71 construct();
74 OMySQLTable::OMySQLTable(sdbcx::OCollection* _pTables, const Reference<XConnection>& _xConnection,
75 const OUString& Name, const OUString& Type, const OUString& Description,
76 const OUString& SchemaName, const OUString& CatalogName,
77 sal_Int32 _nPrivileges)
78 : OTableHelper(_pTables, _xConnection, true, Name, Type, Description, SchemaName, CatalogName)
79 , m_nPrivileges(_nPrivileges)
81 construct();
84 void OMySQLTable::construct()
86 OTableHelper::construct();
87 if (!isNew())
88 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRIVILEGES),
89 PROPERTY_ID_PRIVILEGES, PropertyAttribute::READONLY, &m_nPrivileges,
90 cppu::UnoType<decltype(m_nPrivileges)>::get());
93 ::cppu::IPropertyArrayHelper* OMySQLTable::createArrayHelper(sal_Int32 /*_nId*/) const
95 return doCreateArrayHelper();
98 ::cppu::IPropertyArrayHelper& OMySQLTable::getInfoHelper()
100 return *static_cast<OMySQLTable_PROP*>(this)->getArrayHelper(isNew() ? 1 : 0);
103 sdbcx::OCollection* OMySQLTable::createColumns(const ::std::vector<OUString>& _rNames)
105 OMySQLColumns* pColumns = new OMySQLColumns(*this, m_aMutex, _rNames);
106 pColumns->setParent(this);
107 return pColumns;
110 sdbcx::OCollection* OMySQLTable::createKeys(const ::std::vector<OUString>& _rNames)
112 return new OMySQLKeysHelper(this, m_aMutex, _rNames);
115 sdbcx::OCollection* OMySQLTable::createIndexes(const ::std::vector<OUString>& _rNames)
117 return new OIndexesHelper(this, m_aMutex, _rNames);
120 Sequence<sal_Int8> OMySQLTable::getUnoTunnelId()
122 static ::cppu::OImplementationId implId;
124 return implId.getImplementationId();
127 // css::lang::XUnoTunnel
129 sal_Int64 OMySQLTable::getSomething(const Sequence<sal_Int8>& rId)
131 return (isUnoTunnelId<OMySQLTable>(rId)) ? reinterpret_cast<sal_Int64>(this)
132 : OTable_TYPEDEF::getSomething(rId);
135 // XAlterTable
136 void SAL_CALL OMySQLTable::alterColumnByName(const OUString& colName,
137 const Reference<XPropertySet>& descriptor)
139 ::osl::MutexGuard aGuard(m_aMutex);
140 checkDisposed(
141 #ifdef __GNUC__
142 ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper.bDisposed
143 #else
144 rBHelper.bDisposed
145 #endif
148 if (!m_xColumns || !m_xColumns->hasByName(colName))
149 throw NoSuchElementException(colName, *this);
151 if (!isNew())
153 // first we have to check what should be altered
154 Reference<XPropertySet> xProp;
155 m_xColumns->getByName(colName) >>= xProp;
156 // first check the types
157 sal_Int32 nOldType = 0, nNewType = 0, nOldPrec = 0, nNewPrec = 0, nOldScale = 0,
158 nNewScale = 0;
160 ::dbtools::OPropertyMap& rProp = OMetaConnection::getPropMap();
161 xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPE)) >>= nOldType;
162 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPE)) >>= nNewType;
163 // and precisions and scale
164 xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_PRECISION)) >>= nOldPrec;
165 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_PRECISION)) >>= nNewPrec;
166 xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_SCALE)) >>= nOldScale;
167 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_SCALE)) >>= nNewScale;
168 // second: check the "is nullable" value
169 sal_Int32 nOldNullable = 0, nNewNullable = 0;
170 xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_ISNULLABLE)) >>= nOldNullable;
171 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_ISNULLABLE)) >>= nNewNullable;
173 // check also the auto_increment
174 bool bOldAutoIncrement = false, bAutoIncrement = false;
175 xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT))
176 >>= bOldAutoIncrement;
177 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT))
178 >>= bAutoIncrement;
179 bool bColumnNameChanged = false;
180 OUString sOldDesc, sNewDesc;
181 xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_DESCRIPTION)) >>= sOldDesc;
182 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_DESCRIPTION)) >>= sNewDesc;
184 if (nOldType != nNewType || nOldPrec != nNewPrec || nOldScale != nNewScale
185 || nNewNullable != nOldNullable || bOldAutoIncrement != bAutoIncrement
186 || sOldDesc != sNewDesc)
188 // special handling because they changed the type names to distinguish
189 // if a column should be an auto_increment one
190 if (bOldAutoIncrement != bAutoIncrement)
192 OUString sTypeName;
193 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPENAME))
194 >>= sTypeName;
196 static const char s_sAutoIncrement[] = "auto_increment";
197 if (bAutoIncrement)
199 if (sTypeName.indexOf(s_sAutoIncrement) == -1)
201 sTypeName += OUString::Concat(" ") + s_sAutoIncrement;
202 descriptor->setPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPENAME),
203 makeAny(sTypeName));
206 else
208 if (!sTypeName.isEmpty())
210 sal_Int32 nIndex = sTypeName.indexOf(s_sAutoIncrement);
211 if (nIndex != -1)
213 sTypeName = sTypeName.copy(0, nIndex);
214 descriptor->setPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPENAME),
215 makeAny(sTypeName));
220 alterColumnType(nNewType, colName, descriptor);
221 bColumnNameChanged = true;
224 // third: check the default values
225 OUString sNewDefault, sOldDefault;
226 xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_DEFAULTVALUE)) >>= sOldDefault;
227 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_DEFAULTVALUE))
228 >>= sNewDefault;
230 if (!sOldDefault.isEmpty())
232 dropDefaultValue(colName);
233 if (!sNewDefault.isEmpty() && sOldDefault != sNewDefault)
234 alterDefaultValue(sNewDefault, colName);
236 else if (!sNewDefault.isEmpty())
237 alterDefaultValue(sNewDefault, colName);
239 // now we should look if the name of the column changed
240 OUString sNewColumnName;
241 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_NAME)) >>= sNewColumnName;
242 if (!sNewColumnName.equalsIgnoreAsciiCase(colName) && !bColumnNameChanged)
244 const OUString sQuote = getMetaData()->getIdentifierQuoteString();
245 OUString sSql = getAlterTableColumnPart() + " CHANGE "
246 + ::dbtools::quoteName(sQuote, colName) + " "
247 + OTables::adjustSQL(::dbtools::createStandardColumnPart(
248 descriptor, getConnection(), static_cast<OTables*>(m_pTables),
249 getTypeCreatePattern()));
250 executeStatement(sSql);
252 m_xColumns->refresh();
254 else
256 if (m_xColumns)
258 m_xColumns->dropByName(colName);
259 m_xColumns->appendByDescriptor(descriptor);
264 void OMySQLTable::alterColumnType(sal_Int32 nNewType, const OUString& _rColName,
265 const Reference<XPropertySet>& _xDescriptor)
267 const OUString sQuote = getMetaData()->getIdentifierQuoteString();
268 OUString sSql
269 = getAlterTableColumnPart() + " CHANGE " + ::dbtools::quoteName(sQuote, _rColName) + " ";
271 rtl::Reference<OColumn> pColumn = new OColumn(true);
272 ::comphelper::copyProperties(_xDescriptor, pColumn);
273 pColumn->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE),
274 makeAny(nNewType));
276 sSql += OTables::adjustSQL(::dbtools::createStandardColumnPart(
277 pColumn, getConnection(), static_cast<OTables*>(m_pTables), getTypeCreatePattern()));
278 executeStatement(sSql);
281 OUString OMySQLTable::getTypeCreatePattern() const { return "(M,D)"; }
283 void OMySQLTable::alterDefaultValue(std::u16string_view _sNewDefault, const OUString& _rColName)
285 const OUString sQuote = getMetaData()->getIdentifierQuoteString();
286 OUString sSql = getAlterTableColumnPart() + " ALTER " + ::dbtools::quoteName(sQuote, _rColName)
287 + " SET DEFAULT '" + _sNewDefault + "'";
289 executeStatement(sSql);
292 void OMySQLTable::dropDefaultValue(const OUString& _rColName)
294 const OUString sQuote = getMetaData()->getIdentifierQuoteString();
295 OUString sSql = getAlterTableColumnPart() + " ALTER " + ::dbtools::quoteName(sQuote, _rColName)
296 + " DROP DEFAULT";
298 executeStatement(sSql);
301 OUString OMySQLTable::getAlterTableColumnPart() const
303 OUString sSql("ALTER TABLE ");
305 OUString sComposedName(
306 ::dbtools::composeTableName(getMetaData(), m_CatalogName, m_SchemaName, m_Name, true,
307 ::dbtools::EComposeRule::InTableDefinitions));
308 sSql += sComposedName;
310 return sSql;
313 void OMySQLTable::executeStatement(const OUString& _rStatement)
315 OUString sSQL = _rStatement;
316 if (sSQL.endsWith(","))
317 sSQL = sSQL.replaceAt(sSQL.getLength() - 1, 1, ")");
319 Reference<XStatement> xStmt = getConnection()->createStatement();
320 if (xStmt.is())
322 xStmt->execute(sSQL);
323 ::comphelper::disposeComponent(xStmt);
327 OUString OMySQLTable::getRenameStart() const { return "RENAME TABLE "; }
329 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */