bump product version to 4.1.6.2
[LibreOffice.git] / connectivity / source / drivers / mysql / YTable.cxx
blobefc80a2ae4c92edbe86586e99237b72760dfe2ff
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 <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"
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
56 namespace mysql
58 class OMySQLKeysHelper : public OKeysHelper
60 protected:
61 // -----------------------------------------------------------------------------
62 virtual OUString getDropForeignKey() const
64 return OUString(" DROP FOREIGN KEY ");
66 public:
67 OMySQLKeysHelper( OTableHelper* _pTable,
68 ::osl::Mutex& _rMutex,
69 const TStringVector& _rVector
70 ) : OKeysHelper(_pTable,_rMutex,_rVector){}
76 OMySQLTable::OMySQLTable( sdbcx::OCollection* _pTables,
77 const Reference< XConnection >& _xConnection)
78 :OTableHelper(_pTables,_xConnection,sal_True)
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 Privilege::SELECT;
90 construct();
92 // -------------------------------------------------------------------------
93 OMySQLTable::OMySQLTable( sdbcx::OCollection* _pTables,
94 const Reference< XConnection >& _xConnection,
95 const OUString& _Name,
96 const OUString& _Type,
97 const OUString& _Description ,
98 const OUString& _SchemaName,
99 const 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 , m_nPrivileges(_nPrivileges)
111 construct();
113 // -------------------------------------------------------------------------
114 void OMySQLTable::construct()
116 OTableHelper::construct();
117 if ( !isNew() )
118 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRIVILEGES), PROPERTY_ID_PRIVILEGES,PropertyAttribute::READONLY,&m_nPrivileges, ::getCppuType(&m_nPrivileges));
120 // -----------------------------------------------------------------------------
121 ::cppu::IPropertyArrayHelper* OMySQLTable::createArrayHelper( sal_Int32 /*_nId*/ ) const
123 return doCreateArrayHelper();
125 // -------------------------------------------------------------------------
126 ::cppu::IPropertyArrayHelper & OMySQLTable::getInfoHelper()
128 return *static_cast<OMySQLTable_PROP*>(const_cast<OMySQLTable*>(this))->getArrayHelper(isNew() ? 1 : 0);
130 // -----------------------------------------------------------------------------
131 sdbcx::OCollection* OMySQLTable::createColumns(const TStringVector& _rNames)
133 OMySQLColumns* pColumns = new OMySQLColumns(*this,sal_True,m_aMutex,_rNames);
134 pColumns->setParent(this);
135 return pColumns;
137 // -----------------------------------------------------------------------------
138 sdbcx::OCollection* OMySQLTable::createKeys(const TStringVector& _rNames)
140 return new OMySQLKeysHelper(this,m_aMutex,_rNames);
142 // -----------------------------------------------------------------------------
143 sdbcx::OCollection* OMySQLTable::createIndexes(const TStringVector& _rNames)
145 return new OIndexesHelper(this,m_aMutex,_rNames);
147 //--------------------------------------------------------------------------
148 Sequence< sal_Int8 > OMySQLTable::getUnoTunnelImplementationId()
150 static ::cppu::OImplementationId * pId = 0;
151 if (! pId)
153 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
154 if (! pId)
156 static ::cppu::OImplementationId aId;
157 pId = &aId;
160 return pId->getImplementationId();
163 // com::sun::star::lang::XUnoTunnel
164 //------------------------------------------------------------------
165 sal_Int64 OMySQLTable::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException)
167 return (rId.getLength() == 16 && 0 == memcmp(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) )
168 ? reinterpret_cast< sal_Int64 >( this )
169 : OTable_TYPEDEF::getSomething(rId);
171 // -------------------------------------------------------------------------
172 // XAlterTable
173 void SAL_CALL OMySQLTable::alterColumnByName( const OUString& colName, const Reference< XPropertySet >& descriptor ) throw(SQLException, NoSuchElementException, RuntimeException)
175 ::osl::MutexGuard aGuard(m_aMutex);
176 checkDisposed(
177 #ifdef __GNUC__
178 ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper.bDisposed
179 #else
180 rBHelper.bDisposed
181 #endif
184 if ( m_pColumns && !m_pColumns->hasByName(colName) )
185 throw NoSuchElementException(colName,*this);
188 if ( !isNew() )
190 // first we have to check what should be altered
191 Reference<XPropertySet> xProp;
192 m_pColumns->getByName(colName) >>= xProp;
193 // first check the types
194 sal_Int32 nOldType = 0,nNewType = 0,nOldPrec = 0,nNewPrec = 0,nOldScale = 0,nNewScale = 0;
196 ::dbtools::OPropertyMap& rProp = OMetaConnection::getPropMap();
197 xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPE)) >>= nOldType;
198 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPE)) >>= nNewType;
199 // and precsions and scale
200 xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_PRECISION)) >>= nOldPrec;
201 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_PRECISION))>>= nNewPrec;
202 xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_SCALE)) >>= nOldScale;
203 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_SCALE)) >>= nNewScale;
204 // second: check the "is nullable" value
205 sal_Int32 nOldNullable = 0,nNewNullable = 0;
206 xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_ISNULLABLE)) >>= nOldNullable;
207 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_ISNULLABLE)) >>= nNewNullable;
209 // check also the auto_increment
210 sal_Bool bOldAutoIncrement = sal_False,bAutoIncrement = sal_False;
211 xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT)) >>= bOldAutoIncrement;
212 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT)) >>= bAutoIncrement;
213 bool bColumnNameChanged = false;
214 OUString sOldDesc,sNewDesc;
215 xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_DESCRIPTION)) >>= sOldDesc;
216 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_DESCRIPTION)) >>= sNewDesc;
218 if ( nOldType != nNewType
219 || nOldPrec != nNewPrec
220 || nOldScale != nNewScale
221 || nNewNullable != nOldNullable
222 || bOldAutoIncrement != bAutoIncrement
223 || sOldDesc != sNewDesc )
225 // special handling because they change dthe type names to distinguish
226 // if a column should be an auto_incmrement one
227 if ( bOldAutoIncrement != bAutoIncrement )
229 OUString sTypeName;
230 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPENAME)) >>= sTypeName;
232 static OUString s_sAutoIncrement("auto_increment");
233 if ( bAutoIncrement )
235 if ( sTypeName.indexOf(s_sAutoIncrement) == -1 )
237 sTypeName += OUString(" ");
238 sTypeName += s_sAutoIncrement;
241 else
243 sal_Int32 nIndex = 0;
244 if ( !sTypeName.isEmpty() && (nIndex = sTypeName.indexOf(s_sAutoIncrement)) != -1 )
246 sTypeName = sTypeName.copy(0,nIndex);
247 descriptor->setPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPENAME),makeAny(sTypeName));
251 alterColumnType(nNewType,colName,descriptor);
252 bColumnNameChanged = true;
255 // third: check the default values
256 OUString sNewDefault,sOldDefault;
257 xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_DEFAULTVALUE)) >>= sOldDefault;
258 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_DEFAULTVALUE)) >>= sNewDefault;
260 if(!sOldDefault.isEmpty())
262 dropDefaultValue(colName);
263 if(!sNewDefault.isEmpty() && sOldDefault != sNewDefault)
264 alterDefaultValue(sNewDefault,colName);
266 else if(!sNewDefault.isEmpty())
267 alterDefaultValue(sNewDefault,colName);
269 // now we should look if the name of the column changed
270 OUString sNewColumnName;
271 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_NAME)) >>= sNewColumnName;
272 if ( !sNewColumnName.equalsIgnoreAsciiCase(colName) && !bColumnNameChanged )
274 OUString sSql = getAlterTableColumnPart();
275 sSql += OUString(" CHANGE ");
276 const OUString sQuote = getMetaData()->getIdentifierQuoteString( );
277 sSql += ::dbtools::quoteName(sQuote,colName);
278 sSql += OUString(" ");
279 sSql += OTables::adjustSQL(::dbtools::createStandardColumnPart(descriptor,getConnection(),static_cast<OTables*>(m_pTables),getTypeCreatePattern()));
280 executeStatement(sSql);
282 m_pColumns->refresh();
284 else
286 if(m_pColumns)
288 m_pColumns->dropByName(colName);
289 m_pColumns->appendByDescriptor(descriptor);
294 // -----------------------------------------------------------------------------
295 void OMySQLTable::alterColumnType(sal_Int32 nNewType,const OUString& _rColName, const Reference<XPropertySet>& _xDescriptor)
297 OUString sSql = getAlterTableColumnPart();
298 sSql += OUString(" CHANGE ");
299 const OUString sQuote = getMetaData()->getIdentifierQuoteString( );
300 sSql += ::dbtools::quoteName(sQuote,_rColName);
301 sSql += OUString(" ");
303 OColumn* pColumn = new OColumn(sal_True);
304 Reference<XPropertySet> xProp = pColumn;
305 ::comphelper::copyProperties(_xDescriptor,xProp);
306 xProp->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE),makeAny(nNewType));
308 sSql += OTables::adjustSQL(::dbtools::createStandardColumnPart(xProp,getConnection(),static_cast<OTables*>(m_pTables),getTypeCreatePattern()));
309 executeStatement(sSql);
311 // -----------------------------------------------------------------------------
312 OUString OMySQLTable::getTypeCreatePattern() const
314 static const OUString s_sCreatePattern("(M,D)");
315 return s_sCreatePattern;
317 // -----------------------------------------------------------------------------
318 void OMySQLTable::alterDefaultValue(const OUString& _sNewDefault,const OUString& _rColName)
320 OUString sSql = getAlterTableColumnPart();
321 sSql += OUString(" ALTER ");
323 const OUString sQuote = getMetaData()->getIdentifierQuoteString( );
324 sSql += ::dbtools::quoteName(sQuote,_rColName);
325 sSql += OUString(" SET DEFAULT '") + _sNewDefault;
326 sSql += OUString("'");
328 executeStatement(sSql);
330 // -----------------------------------------------------------------------------
331 void OMySQLTable::dropDefaultValue(const OUString& _rColName)
333 OUString sSql = getAlterTableColumnPart();
334 sSql += OUString(" ALTER ");
336 const OUString sQuote = getMetaData()->getIdentifierQuoteString( );
337 sSql += ::dbtools::quoteName(sQuote,_rColName);
338 sSql += OUString(" DROP DEFAULT");
340 executeStatement(sSql);
342 // -----------------------------------------------------------------------------
343 OUString OMySQLTable::getAlterTableColumnPart()
345 OUString sSql( "ALTER TABLE " );
347 OUString sComposedName(
348 ::dbtools::composeTableName( getMetaData(), m_CatalogName, m_SchemaName, m_Name, sal_True, ::dbtools::eInTableDefinitions ) );
349 sSql += sComposedName;
351 return sSql;
353 // -----------------------------------------------------------------------------
354 void OMySQLTable::executeStatement(const OUString& _rStatement )
356 OUString sSQL = _rStatement;
357 if(sSQL.lastIndexOf(',') == (sSQL.getLength()-1))
358 sSQL = sSQL.replaceAt(sSQL.getLength()-1,1,OUString(")"));
360 Reference< XStatement > xStmt = getConnection()->createStatement( );
361 if ( xStmt.is() )
363 xStmt->execute(sSQL);
364 ::comphelper::disposeComponent(xStmt);
367 // -----------------------------------------------------------------------------
368 OUString OMySQLTable::getRenameStart() const
370 return OUString("RENAME TABLE ");
376 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */