Branch data Line data Source code
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 <string.h>
21 : : #include "mysql/YTable.hxx"
22 : : #include "mysql/YTables.hxx"
23 : : #include <com/sun/star/sdbc/XRow.hpp>
24 : : #include <com/sun/star/sdbc/XResultSet.hpp>
25 : : #include <com/sun/star/sdbcx/KeyType.hpp>
26 : : #include <com/sun/star/sdbc/KeyRule.hpp>
27 : : #include <cppuhelper/typeprovider.hxx>
28 : : #include <com/sun/star/lang/DisposedException.hpp>
29 : : #include <com/sun/star/sdbc/ColumnValue.hpp>
30 : : #include <com/sun/star/sdbcx/Privilege.hpp>
31 : : #include <comphelper/property.hxx>
32 : : #include <comphelper/extract.hxx>
33 : : #include <comphelper/types.hxx>
34 : : #include "connectivity/dbtools.hxx"
35 : : #include "connectivity/sdbcx/VColumn.hxx"
36 : : #include "connectivity/TKeys.hxx"
37 : : #include "connectivity/TIndexes.hxx"
38 : : #include "connectivity/TColumnsHelper.hxx"
39 : : #include "mysql/YCatalog.hxx"
40 : : #include "mysql/YColumns.hxx"
41 : : #include "TConnection.hxx"
42 : :
43 : :
44 : : using namespace ::comphelper;
45 : : using namespace connectivity::mysql;
46 : : using namespace connectivity::sdbcx;
47 : : using namespace connectivity;
48 : : using namespace ::com::sun::star::uno;
49 : : using namespace ::com::sun::star::beans;
50 : : using namespace ::com::sun::star::sdbcx;
51 : : using namespace ::com::sun::star::sdbc;
52 : : using namespace ::com::sun::star::container;
53 : : using namespace ::com::sun::star::lang;
54 : : namespace connectivity
55 : : {
56 : : namespace mysql
57 : : {
58 : 0 : class OMySQLKeysHelper : public OKeysHelper
59 : : {
60 : : protected:
61 : : // -----------------------------------------------------------------------------
62 : 0 : virtual ::rtl::OUString getDropForeignKey() const
63 : : {
64 : 0 : return ::rtl::OUString(" DROP FOREIGN KEY ");
65 : : }
66 : : public:
67 : 0 : OMySQLKeysHelper( OTableHelper* _pTable,
68 : : ::osl::Mutex& _rMutex,
69 : : const TStringVector& _rVector
70 : 0 : ) : OKeysHelper(_pTable,_rMutex,_rVector){}
71 : :
72 : : };
73 : : }
74 : : }
75 : :
76 : 0 : OMySQLTable::OMySQLTable( sdbcx::OCollection* _pTables,
77 : : const Reference< XConnection >& _xConnection)
78 : 0 : :OTableHelper(_pTables,_xConnection,sal_True)
79 : : {
80 : : // we create a new table here, so we should have all the rights or ;-)
81 : : m_nPrivileges = Privilege::DROP |
82 : : Privilege::REFERENCE |
83 : : Privilege::ALTER |
84 : : Privilege::CREATE |
85 : : Privilege::READ |
86 : : Privilege::DELETE |
87 : : Privilege::UPDATE |
88 : : Privilege::INSERT |
89 : 0 : Privilege::SELECT;
90 : 0 : construct();
91 : 0 : }
92 : : // -------------------------------------------------------------------------
93 : 0 : OMySQLTable::OMySQLTable( sdbcx::OCollection* _pTables,
94 : : const Reference< XConnection >& _xConnection,
95 : : const ::rtl::OUString& _Name,
96 : : const ::rtl::OUString& _Type,
97 : : const ::rtl::OUString& _Description ,
98 : : const ::rtl::OUString& _SchemaName,
99 : : const ::rtl::OUString& _CatalogName,
100 : : sal_Int32 _nPrivileges
101 : : ) : OTableHelper( _pTables,
102 : : _xConnection,
103 : : sal_True,
104 : : _Name,
105 : : _Type,
106 : : _Description,
107 : : _SchemaName,
108 : : _CatalogName)
109 : 0 : , m_nPrivileges(_nPrivileges)
110 : : {
111 : 0 : construct();
112 : 0 : }
113 : : // -------------------------------------------------------------------------
114 : 0 : void OMySQLTable::construct()
115 : : {
116 : 0 : OTableHelper::construct();
117 : 0 : if ( !isNew() )
118 : 0 : registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRIVILEGES), PROPERTY_ID_PRIVILEGES,PropertyAttribute::READONLY,&m_nPrivileges, ::getCppuType(&m_nPrivileges));
119 : 0 : }
120 : : // -----------------------------------------------------------------------------
121 : 0 : ::cppu::IPropertyArrayHelper* OMySQLTable::createArrayHelper( sal_Int32 /*_nId*/ ) const
122 : : {
123 : 0 : return doCreateArrayHelper();
124 : : }
125 : : // -------------------------------------------------------------------------
126 : 0 : ::cppu::IPropertyArrayHelper & OMySQLTable::getInfoHelper()
127 : : {
128 : 0 : return *static_cast<OMySQLTable_PROP*>(const_cast<OMySQLTable*>(this))->getArrayHelper(isNew() ? 1 : 0);
129 : : }
130 : : // -----------------------------------------------------------------------------
131 : 0 : sdbcx::OCollection* OMySQLTable::createColumns(const TStringVector& _rNames)
132 : : {
133 : 0 : OMySQLColumns* pColumns = new OMySQLColumns(*this,sal_True,m_aMutex,_rNames);
134 : 0 : pColumns->setParent(this);
135 : 0 : return pColumns;
136 : : }
137 : : // -----------------------------------------------------------------------------
138 : 0 : sdbcx::OCollection* OMySQLTable::createKeys(const TStringVector& _rNames)
139 : : {
140 : 0 : return new OMySQLKeysHelper(this,m_aMutex,_rNames);
141 : : }
142 : : // -----------------------------------------------------------------------------
143 : 0 : sdbcx::OCollection* OMySQLTable::createIndexes(const TStringVector& _rNames)
144 : : {
145 : 0 : return new OIndexesHelper(this,m_aMutex,_rNames);
146 : : }
147 : : //--------------------------------------------------------------------------
148 : 0 : Sequence< sal_Int8 > OMySQLTable::getUnoTunnelImplementationId()
149 : : {
150 : : static ::cppu::OImplementationId * pId = 0;
151 : 0 : if (! pId)
152 : : {
153 : 0 : ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
154 : 0 : if (! pId)
155 : : {
156 : 0 : static ::cppu::OImplementationId aId;
157 : 0 : pId = &aId;
158 : 0 : }
159 : : }
160 : 0 : return pId->getImplementationId();
161 : : }
162 : :
163 : : // com::sun::star::lang::XUnoTunnel
164 : : //------------------------------------------------------------------
165 : 0 : sal_Int64 OMySQLTable::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException)
166 : : {
167 : 0 : return (rId.getLength() == 16 && 0 == memcmp(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) )
168 : : ? reinterpret_cast< sal_Int64 >( this )
169 : 0 : : OTable_TYPEDEF::getSomething(rId);
170 : : }
171 : : // -------------------------------------------------------------------------
172 : : // XAlterTable
173 : 0 : void SAL_CALL OMySQLTable::alterColumnByName( const ::rtl::OUString& colName, const Reference< XPropertySet >& descriptor ) throw(SQLException, NoSuchElementException, RuntimeException)
174 : : {
175 : 0 : ::osl::MutexGuard aGuard(m_aMutex);
176 : : checkDisposed(
177 : : #ifdef GCC
178 : : ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper.bDisposed
179 : : #else
180 : : rBHelper.bDisposed
181 : : #endif
182 : 0 : );
183 : :
184 : 0 : if ( m_pColumns && !m_pColumns->hasByName(colName) )
185 : 0 : throw NoSuchElementException(colName,*this);
186 : :
187 : :
188 : 0 : if ( !isNew() )
189 : : {
190 : : // first we have to check what should be altered
191 : 0 : Reference<XPropertySet> xProp;
192 : 0 : m_pColumns->getByName(colName) >>= xProp;
193 : : // first check the types
194 : 0 : sal_Int32 nOldType = 0,nNewType = 0,nOldPrec = 0,nNewPrec = 0,nOldScale = 0,nNewScale = 0;
195 : :
196 : 0 : ::dbtools::OPropertyMap& rProp = OMetaConnection::getPropMap();
197 : 0 : xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPE)) >>= nOldType;
198 : 0 : descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPE)) >>= nNewType;
199 : : // and precsions and scale
200 : 0 : xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_PRECISION)) >>= nOldPrec;
201 : 0 : descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_PRECISION))>>= nNewPrec;
202 : 0 : xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_SCALE)) >>= nOldScale;
203 : 0 : descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_SCALE)) >>= nNewScale;
204 : : // second: check the "is nullable" value
205 : 0 : sal_Int32 nOldNullable = 0,nNewNullable = 0;
206 : 0 : xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_ISNULLABLE)) >>= nOldNullable;
207 : 0 : descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_ISNULLABLE)) >>= nNewNullable;
208 : :
209 : : // check also the auto_increment
210 : 0 : sal_Bool bOldAutoIncrement = sal_False,bAutoIncrement = sal_False;
211 : 0 : xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT)) >>= bOldAutoIncrement;
212 : 0 : descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT)) >>= bAutoIncrement;
213 : 0 : bool bColumnNameChanged = false;
214 : 0 : ::rtl::OUString sOldDesc,sNewDesc;
215 : 0 : xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_DESCRIPTION)) >>= sOldDesc;
216 : 0 : descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_DESCRIPTION)) >>= sNewDesc;
217 : :
218 : 0 : if ( nOldType != nNewType
219 : : || nOldPrec != nNewPrec
220 : : || nOldScale != nNewScale
221 : : || nNewNullable != nOldNullable
222 : : || bOldAutoIncrement != bAutoIncrement
223 : 0 : || sOldDesc != sNewDesc )
224 : : {
225 : : // special handling because they change dthe type names to distinguish
226 : : // if a column should be an auto_incmrement one
227 : 0 : if ( bOldAutoIncrement != bAutoIncrement )
228 : : {
229 : 0 : ::rtl::OUString sTypeName;
230 : 0 : descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPENAME)) >>= sTypeName;
231 : :
232 : 0 : static ::rtl::OUString s_sAutoIncrement("auto_increment");
233 : 0 : if ( bAutoIncrement )
234 : : {
235 : 0 : if ( sTypeName.indexOf(s_sAutoIncrement) == -1 )
236 : : {
237 : 0 : sTypeName += ::rtl::OUString(" ");
238 : 0 : sTypeName += s_sAutoIncrement;
239 : : }
240 : : }
241 : : else
242 : : {
243 : 0 : sal_Int32 nIndex = 0;
244 : 0 : if ( !sTypeName.isEmpty() && (nIndex = sTypeName.indexOf(s_sAutoIncrement)) != -1 )
245 : : {
246 : 0 : sTypeName = sTypeName.copy(0,nIndex);
247 : 0 : descriptor->setPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPENAME),makeAny(sTypeName));
248 : : }
249 : 0 : }
250 : : }
251 : 0 : alterColumnType(nNewType,colName,descriptor);
252 : 0 : bColumnNameChanged = true;
253 : : }
254 : :
255 : : // third: check the default values
256 : 0 : ::rtl::OUString sNewDefault,sOldDefault;
257 : 0 : xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_DEFAULTVALUE)) >>= sOldDefault;
258 : 0 : descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_DEFAULTVALUE)) >>= sNewDefault;
259 : :
260 : 0 : if(!sOldDefault.isEmpty())
261 : : {
262 : 0 : dropDefaultValue(colName);
263 : 0 : if(!sNewDefault.isEmpty() && sOldDefault != sNewDefault)
264 : 0 : alterDefaultValue(sNewDefault,colName);
265 : : }
266 : 0 : else if(!sNewDefault.isEmpty())
267 : 0 : alterDefaultValue(sNewDefault,colName);
268 : :
269 : : // now we should look if the name of the column changed
270 : 0 : ::rtl::OUString sNewColumnName;
271 : 0 : descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_NAME)) >>= sNewColumnName;
272 : 0 : if ( !sNewColumnName.equalsIgnoreAsciiCase(colName) && !bColumnNameChanged )
273 : : {
274 : 0 : ::rtl::OUString sSql = getAlterTableColumnPart();
275 : 0 : sSql += ::rtl::OUString(" CHANGE ");
276 : 0 : const ::rtl::OUString sQuote = getMetaData()->getIdentifierQuoteString( );
277 : 0 : sSql += ::dbtools::quoteName(sQuote,colName);
278 : 0 : sSql += ::rtl::OUString(" ");
279 : 0 : sSql += OTables::adjustSQL(::dbtools::createStandardColumnPart(descriptor,getConnection(),static_cast<OTables*>(m_pTables),getTypeCreatePattern()));
280 : 0 : executeStatement(sSql);
281 : : }
282 : 0 : m_pColumns->refresh();
283 : : }
284 : : else
285 : : {
286 : 0 : if(m_pColumns)
287 : : {
288 : 0 : m_pColumns->dropByName(colName);
289 : 0 : m_pColumns->appendByDescriptor(descriptor);
290 : : }
291 : 0 : }
292 : :
293 : 0 : }
294 : : // -----------------------------------------------------------------------------
295 : 0 : void OMySQLTable::alterColumnType(sal_Int32 nNewType,const ::rtl::OUString& _rColName, const Reference<XPropertySet>& _xDescriptor)
296 : : {
297 : 0 : ::rtl::OUString sSql = getAlterTableColumnPart();
298 : 0 : sSql += ::rtl::OUString(" CHANGE ");
299 : 0 : const ::rtl::OUString sQuote = getMetaData()->getIdentifierQuoteString( );
300 : 0 : sSql += ::dbtools::quoteName(sQuote,_rColName);
301 : 0 : sSql += ::rtl::OUString(" ");
302 : :
303 : 0 : OColumn* pColumn = new OColumn(sal_True);
304 : 0 : Reference<XPropertySet> xProp = pColumn;
305 : 0 : ::comphelper::copyProperties(_xDescriptor,xProp);
306 : 0 : xProp->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE),makeAny(nNewType));
307 : :
308 : 0 : sSql += OTables::adjustSQL(::dbtools::createStandardColumnPart(xProp,getConnection(),static_cast<OTables*>(m_pTables),getTypeCreatePattern()));
309 : 0 : executeStatement(sSql);
310 : 0 : }
311 : : // -----------------------------------------------------------------------------
312 : 0 : ::rtl::OUString OMySQLTable::getTypeCreatePattern() const
313 : : {
314 : 0 : static const ::rtl::OUString s_sCreatePattern("(M,D)");
315 : 0 : return s_sCreatePattern;
316 : : }
317 : : // -----------------------------------------------------------------------------
318 : 0 : void OMySQLTable::alterDefaultValue(const ::rtl::OUString& _sNewDefault,const ::rtl::OUString& _rColName)
319 : : {
320 : 0 : ::rtl::OUString sSql = getAlterTableColumnPart();
321 : 0 : sSql += ::rtl::OUString(" ALTER ");
322 : :
323 : 0 : const ::rtl::OUString sQuote = getMetaData()->getIdentifierQuoteString( );
324 : 0 : sSql += ::dbtools::quoteName(sQuote,_rColName);
325 : 0 : sSql += ::rtl::OUString(" SET DEFAULT '") + _sNewDefault;
326 : 0 : sSql += ::rtl::OUString("'");
327 : :
328 : 0 : executeStatement(sSql);
329 : 0 : }
330 : : // -----------------------------------------------------------------------------
331 : 0 : void OMySQLTable::dropDefaultValue(const ::rtl::OUString& _rColName)
332 : : {
333 : 0 : ::rtl::OUString sSql = getAlterTableColumnPart();
334 : 0 : sSql += ::rtl::OUString(" ALTER ");
335 : :
336 : 0 : const ::rtl::OUString sQuote = getMetaData()->getIdentifierQuoteString( );
337 : 0 : sSql += ::dbtools::quoteName(sQuote,_rColName);
338 : 0 : sSql += ::rtl::OUString(" DROP DEFAULT");
339 : :
340 : 0 : executeStatement(sSql);
341 : 0 : }
342 : : // -----------------------------------------------------------------------------
343 : 0 : ::rtl::OUString OMySQLTable::getAlterTableColumnPart()
344 : : {
345 : 0 : ::rtl::OUString sSql( "ALTER TABLE " );
346 : 0 : const ::rtl::OUString sQuote = getMetaData()->getIdentifierQuoteString( );
347 : :
348 : : ::rtl::OUString sComposedName(
349 : 0 : ::dbtools::composeTableName( getMetaData(), m_CatalogName, m_SchemaName, m_Name, sal_True, ::dbtools::eInTableDefinitions ) );
350 : 0 : sSql += sComposedName;
351 : :
352 : 0 : return sSql;
353 : : }
354 : : // -----------------------------------------------------------------------------
355 : 0 : void OMySQLTable::executeStatement(const ::rtl::OUString& _rStatement )
356 : : {
357 : 0 : ::rtl::OUString sSQL = _rStatement;
358 : 0 : if(sSQL.lastIndexOf(',') == (sSQL.getLength()-1))
359 : 0 : sSQL = sSQL.replaceAt(sSQL.getLength()-1,1,::rtl::OUString(")"));
360 : :
361 : 0 : Reference< XStatement > xStmt = getConnection()->createStatement( );
362 : 0 : if ( xStmt.is() )
363 : : {
364 : 0 : xStmt->execute(sSQL);
365 : 0 : ::comphelper::disposeComponent(xStmt);
366 : 0 : }
367 : 0 : }
368 : : // -----------------------------------------------------------------------------
369 : 0 : ::rtl::OUString OMySQLTable::getRenameStart() const
370 : : {
371 : 0 : return ::rtl::OUString("RENAME TABLE ");
372 : : }
373 : :
374 : :
375 : :
376 : :
377 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|