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 <com/sun/star/beans/PropertyAttribute.hpp>
23 #include <com/sun/star/sdbcx/Privilege.hpp>
24 #include <comphelper/property.hxx>
25 #include <comphelper/servicehelper.hxx>
26 #include <comphelper/types.hxx>
27 #include <connectivity/dbtools.hxx>
28 #include <connectivity/sdbcx/VColumn.hxx>
29 #include <connectivity/TKeys.hxx>
30 #include <connectivity/TIndexes.hxx>
31 #include <mysql/YColumns.hxx>
32 #include <TConnection.hxx>
34 using namespace ::comphelper
;
35 using namespace connectivity::mysql
;
36 using namespace connectivity::sdbcx
;
37 using namespace connectivity
;
38 using namespace ::com::sun::star::uno
;
39 using namespace ::com::sun::star::beans
;
40 using namespace ::com::sun::star::sdbcx
;
41 using namespace ::com::sun::star::sdbc
;
42 using namespace ::com::sun::star::container
;
43 using namespace ::com::sun::star::lang
;
44 namespace connectivity::mysql
48 class OMySQLKeysHelper
: public OKeysHelper
51 virtual OUString
getDropForeignKey() const override
{ return u
" DROP FOREIGN KEY "_ustr
; }
54 OMySQLKeysHelper(OTableHelper
* _pTable
, ::osl::Mutex
& _rMutex
,
55 const ::std::vector
<OUString
>& _rVector
)
56 : OKeysHelper(_pTable
, _rMutex
, _rVector
)
63 OMySQLTable::OMySQLTable(sdbcx::OCollection
* _pTables
, const Reference
<XConnection
>& _xConnection
)
64 : OTableHelper(_pTables
, _xConnection
, true)
66 // we create a new table here, so we should have all the rights or ;-)
67 m_nPrivileges
= Privilege::DROP
| Privilege::REFERENCE
| Privilege::ALTER
| Privilege::CREATE
68 | Privilege::READ
| Privilege::DELETE
| Privilege::UPDATE
| Privilege::INSERT
73 OMySQLTable::OMySQLTable(sdbcx::OCollection
* _pTables
, const Reference
<XConnection
>& _xConnection
,
74 const OUString
& Name
, const OUString
& Type
, const OUString
& Description
,
75 const OUString
& SchemaName
, const OUString
& CatalogName
,
76 sal_Int32 _nPrivileges
)
77 : OTableHelper(_pTables
, _xConnection
, true, Name
, Type
, Description
, SchemaName
, CatalogName
)
78 , m_nPrivileges(_nPrivileges
)
83 void OMySQLTable::construct()
85 OTableHelper::construct();
87 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRIVILEGES
),
88 PROPERTY_ID_PRIVILEGES
, PropertyAttribute::READONLY
, &m_nPrivileges
,
89 cppu::UnoType
<decltype(m_nPrivileges
)>::get());
92 ::cppu::IPropertyArrayHelper
* OMySQLTable::createArrayHelper(sal_Int32
/*_nId*/) const
94 return doCreateArrayHelper();
97 ::cppu::IPropertyArrayHelper
& OMySQLTable::getInfoHelper()
99 return *static_cast<OMySQLTable_PROP
*>(this)->getArrayHelper(isNew() ? 1 : 0);
102 sdbcx::OCollection
* OMySQLTable::createColumns(const ::std::vector
<OUString
>& _rNames
)
104 OMySQLColumns
* pColumns
= new OMySQLColumns(*this, m_aMutex
, _rNames
);
105 pColumns
->setParent(this);
109 sdbcx::OCollection
* OMySQLTable::createKeys(const ::std::vector
<OUString
>& _rNames
)
111 return new OMySQLKeysHelper(this, m_aMutex
, _rNames
);
114 sdbcx::OCollection
* OMySQLTable::createIndexes(const ::std::vector
<OUString
>& _rNames
)
116 return new OIndexesHelper(this, m_aMutex
, _rNames
);
120 void SAL_CALL
OMySQLTable::alterColumnByName(const OUString
& colName
,
121 const Reference
<XPropertySet
>& descriptor
)
123 ::osl::MutexGuard
aGuard(m_aMutex
);
126 ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper
.bDisposed
132 if (!m_xColumns
|| !m_xColumns
->hasByName(colName
))
133 throw NoSuchElementException(colName
, *this);
137 // first we have to check what should be altered
138 Reference
<XPropertySet
> xProp
;
139 m_xColumns
->getByName(colName
) >>= xProp
;
140 // first check the types
141 sal_Int32 nOldType
= 0, nNewType
= 0, nOldPrec
= 0, nNewPrec
= 0, nOldScale
= 0,
144 ::dbtools::OPropertyMap
& rProp
= OMetaConnection::getPropMap();
145 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPE
)) >>= nOldType
;
146 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPE
)) >>= nNewType
;
147 // and precisions and scale
148 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_PRECISION
)) >>= nOldPrec
;
149 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_PRECISION
)) >>= nNewPrec
;
150 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_SCALE
)) >>= nOldScale
;
151 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_SCALE
)) >>= nNewScale
;
152 // second: check the "is nullable" value
153 sal_Int32 nOldNullable
= 0, nNewNullable
= 0;
154 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_ISNULLABLE
)) >>= nOldNullable
;
155 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_ISNULLABLE
)) >>= nNewNullable
;
157 // check also the auto_increment
158 bool bOldAutoIncrement
= false, bAutoIncrement
= false;
159 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT
))
160 >>= bOldAutoIncrement
;
161 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT
))
163 bool bColumnNameChanged
= false;
164 OUString sOldDesc
, sNewDesc
;
165 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_DESCRIPTION
)) >>= sOldDesc
;
166 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_DESCRIPTION
)) >>= sNewDesc
;
168 if (nOldType
!= nNewType
|| nOldPrec
!= nNewPrec
|| nOldScale
!= nNewScale
169 || nNewNullable
!= nOldNullable
|| bOldAutoIncrement
!= bAutoIncrement
170 || sOldDesc
!= sNewDesc
)
172 // special handling because they changed the type names to distinguish
173 // if a column should be an auto_increment one
174 if (bOldAutoIncrement
!= bAutoIncrement
)
177 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPENAME
))
180 static const char s_sAutoIncrement
[] = "auto_increment";
183 if (sTypeName
.indexOf(s_sAutoIncrement
) == -1)
185 sTypeName
+= OUString::Concat(" ") + s_sAutoIncrement
;
186 descriptor
->setPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPENAME
),
192 if (!sTypeName
.isEmpty())
194 sal_Int32 nIndex
= sTypeName
.indexOf(s_sAutoIncrement
);
197 sTypeName
= sTypeName
.copy(0, nIndex
);
198 descriptor
->setPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPENAME
),
204 alterColumnType(nNewType
, colName
, descriptor
);
205 bColumnNameChanged
= true;
208 // third: check the default values
209 OUString sNewDefault
, sOldDefault
;
210 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_DEFAULTVALUE
)) >>= sOldDefault
;
211 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_DEFAULTVALUE
))
214 if (!sOldDefault
.isEmpty())
216 dropDefaultValue(colName
);
217 if (!sNewDefault
.isEmpty() && sOldDefault
!= sNewDefault
)
218 alterDefaultValue(sNewDefault
, colName
);
220 else if (!sNewDefault
.isEmpty())
221 alterDefaultValue(sNewDefault
, colName
);
223 // now we should look if the name of the column changed
224 OUString sNewColumnName
;
225 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_NAME
)) >>= sNewColumnName
;
226 if (!sNewColumnName
.equalsIgnoreAsciiCase(colName
) && !bColumnNameChanged
)
228 const OUString sQuote
= getMetaData()->getIdentifierQuoteString();
229 OUString sSql
= getAlterTableColumnPart() + " CHANGE "
230 + ::dbtools::quoteName(sQuote
, colName
) + " "
231 + OTables::adjustSQL(::dbtools::createStandardColumnPart(
232 descriptor
, getConnection(), static_cast<OTables
*>(m_pTables
),
233 getTypeCreatePattern()));
234 executeStatement(sSql
);
236 m_xColumns
->refresh();
242 m_xColumns
->dropByName(colName
);
243 m_xColumns
->appendByDescriptor(descriptor
);
248 void OMySQLTable::alterColumnType(sal_Int32 nNewType
, const OUString
& _rColName
,
249 const Reference
<XPropertySet
>& _xDescriptor
)
251 const OUString sQuote
= getMetaData()->getIdentifierQuoteString();
253 = getAlterTableColumnPart() + " CHANGE " + ::dbtools::quoteName(sQuote
, _rColName
) + " ";
255 rtl::Reference
<OColumn
> pColumn
= new OColumn(true);
256 ::comphelper::copyProperties(_xDescriptor
, pColumn
);
257 pColumn
->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE
),
260 sSql
+= OTables::adjustSQL(::dbtools::createStandardColumnPart(
261 pColumn
, getConnection(), static_cast<OTables
*>(m_pTables
), getTypeCreatePattern()));
262 executeStatement(sSql
);
265 OUString
OMySQLTable::getTypeCreatePattern() const { return u
"(M,D)"_ustr
; }
267 void OMySQLTable::alterDefaultValue(std::u16string_view _sNewDefault
, const OUString
& _rColName
)
269 const OUString sQuote
= getMetaData()->getIdentifierQuoteString();
270 OUString sSql
= getAlterTableColumnPart() + " ALTER " + ::dbtools::quoteName(sQuote
, _rColName
)
271 + " SET DEFAULT '" + _sNewDefault
+ "'";
273 executeStatement(sSql
);
276 void OMySQLTable::dropDefaultValue(const OUString
& _rColName
)
278 const OUString sQuote
= getMetaData()->getIdentifierQuoteString();
279 OUString sSql
= getAlterTableColumnPart() + " ALTER " + ::dbtools::quoteName(sQuote
, _rColName
)
282 executeStatement(sSql
);
285 OUString
OMySQLTable::getAlterTableColumnPart() const
287 OUString
sSql(u
"ALTER TABLE "_ustr
);
289 OUString
sComposedName(
290 ::dbtools::composeTableName(getMetaData(), m_CatalogName
, m_SchemaName
, m_Name
, true,
291 ::dbtools::EComposeRule::InTableDefinitions
));
292 sSql
+= sComposedName
;
297 void OMySQLTable::executeStatement(const OUString
& _rStatement
)
299 OUString sSQL
= _rStatement
;
300 if (sSQL
.endsWith(","))
301 sSQL
= sSQL
.replaceAt(sSQL
.getLength() - 1, 1, u
")");
303 Reference
<XStatement
> xStmt
= getConnection()->createStatement();
306 xStmt
->execute(sSQL
);
307 ::comphelper::disposeComponent(xStmt
);
311 OUString
OMySQLTable::getRenameStart() const { return u
"RENAME TABLE "_ustr
; }
313 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */