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 .
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
58 class OMySQLKeysHelper
: public OKeysHelper
61 // -----------------------------------------------------------------------------
62 virtual OUString
getDropForeignKey() const
64 return OUString(" DROP FOREIGN KEY ");
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
|
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
,
109 , m_nPrivileges(_nPrivileges
)
113 // -------------------------------------------------------------------------
114 void OMySQLTable::construct()
116 OTableHelper::construct();
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);
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;
153 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
156 static ::cppu::OImplementationId 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 // -------------------------------------------------------------------------
173 void SAL_CALL
OMySQLTable::alterColumnByName( const OUString
& colName
, const Reference
< XPropertySet
>& descriptor
) throw(SQLException
, NoSuchElementException
, RuntimeException
)
175 ::osl::MutexGuard
aGuard(m_aMutex
);
178 ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper
.bDisposed
184 if ( m_pColumns
&& !m_pColumns
->hasByName(colName
) )
185 throw NoSuchElementException(colName
,*this);
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
)
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
;
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();
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
;
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( );
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: */