1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
49 class OMySQLKeysHelper
: public OKeysHelper
52 virtual OUString
getDropForeignKey() const override
{ return " DROP FOREIGN KEY "; }
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
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
)
84 void OMySQLTable::construct()
86 OTableHelper::construct();
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);
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
);
136 void SAL_CALL
OMySQLTable::alterColumnByName(const OUString
& colName
,
137 const Reference
<XPropertySet
>& descriptor
)
139 ::osl::MutexGuard
aGuard(m_aMutex
);
142 ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper
.bDisposed
148 if (!m_xColumns
|| !m_xColumns
->hasByName(colName
))
149 throw NoSuchElementException(colName
, *this);
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,
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
))
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
)
193 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPENAME
))
196 static const char s_sAutoIncrement
[] = "auto_increment";
199 if (sTypeName
.indexOf(s_sAutoIncrement
) == -1)
201 sTypeName
+= OUString::Concat(" ") + s_sAutoIncrement
;
202 descriptor
->setPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPENAME
),
208 if (!sTypeName
.isEmpty())
210 sal_Int32 nIndex
= sTypeName
.indexOf(s_sAutoIncrement
);
213 sTypeName
= sTypeName
.copy(0, nIndex
);
214 descriptor
->setPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPENAME
),
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
))
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();
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();
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
),
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
)
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
;
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();
322 xStmt
->execute(sSQL
);
323 ::comphelper::disposeComponent(xStmt
);
327 OUString
OMySQLTable::getRenameStart() const { return "RENAME TABLE "; }
329 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */