1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: YTable.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
33 #include "mysql/YTable.hxx"
34 #include "mysql/YTables.hxx"
35 #include <com/sun/star/sdbc/XRow.hpp>
36 #include <com/sun/star/sdbc/XResultSet.hpp>
37 #include <com/sun/star/sdbcx/KeyType.hpp>
38 #include <com/sun/star/sdbc/KeyRule.hpp>
39 #include <cppuhelper/typeprovider.hxx>
40 #include <com/sun/star/lang/DisposedException.hpp>
41 #include <com/sun/star/sdbc/ColumnValue.hpp>
42 #include <com/sun/star/sdbcx/Privilege.hpp>
43 #include <comphelper/property.hxx>
44 #include <comphelper/extract.hxx>
45 #include <comphelper/types.hxx>
46 #include "connectivity/dbtools.hxx"
47 #include "connectivity/sdbcx/VColumn.hxx"
48 #include "connectivity/TKeys.hxx"
49 #include "connectivity/TIndexes.hxx"
50 #include "connectivity/TColumnsHelper.hxx"
51 #include "mysql/YCatalog.hxx"
52 #include "mysql/YColumns.hxx"
53 #include "TConnection.hxx"
56 using namespace ::comphelper
;
57 using namespace connectivity::mysql
;
58 using namespace connectivity::sdbcx
;
59 using namespace connectivity
;
60 using namespace ::com::sun::star::uno
;
61 using namespace ::com::sun::star::beans
;
62 using namespace ::com::sun::star::sdbcx
;
63 using namespace ::com::sun::star::sdbc
;
64 using namespace ::com::sun::star::container
;
65 using namespace ::com::sun::star::lang
;
66 namespace connectivity
70 class OMySQLKeysHelper
: public OKeysHelper
73 // -----------------------------------------------------------------------------
74 virtual ::rtl::OUString
getDropForeignKey() const
76 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" DROP FOREIGN KEY "));
79 OMySQLKeysHelper( OTableHelper
* _pTable
,
80 ::osl::Mutex
& _rMutex
,
81 const TStringVector
& _rVector
82 ) : OKeysHelper(_pTable
,_rMutex
,_rVector
){}
88 OMySQLTable::OMySQLTable( sdbcx::OCollection
* _pTables
,
89 const Reference
< XConnection
>& _xConnection
)
90 :OTableHelper(_pTables
,_xConnection
,sal_True
)
92 // we create a new table here, so we should have all the rights or ;-)
93 m_nPrivileges
= Privilege::DROP
|
94 Privilege::REFERENCE
|
104 // -------------------------------------------------------------------------
105 OMySQLTable::OMySQLTable( sdbcx::OCollection
* _pTables
,
106 const Reference
< XConnection
>& _xConnection
,
107 const ::rtl::OUString
& _Name
,
108 const ::rtl::OUString
& _Type
,
109 const ::rtl::OUString
& _Description
,
110 const ::rtl::OUString
& _SchemaName
,
111 const ::rtl::OUString
& _CatalogName
,
112 sal_Int32 _nPrivileges
113 ) : OTableHelper( _pTables
,
121 , m_nPrivileges(_nPrivileges
)
125 // -------------------------------------------------------------------------
126 void OMySQLTable::construct()
128 OTableHelper::construct();
130 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRIVILEGES
), PROPERTY_ID_PRIVILEGES
,PropertyAttribute::READONLY
,&m_nPrivileges
, ::getCppuType(&m_nPrivileges
));
132 // -----------------------------------------------------------------------------
133 ::cppu::IPropertyArrayHelper
* OMySQLTable::createArrayHelper( sal_Int32
/*_nId*/ ) const
135 return doCreateArrayHelper();
137 // -------------------------------------------------------------------------
138 ::cppu::IPropertyArrayHelper
& OMySQLTable::getInfoHelper()
140 return *static_cast<OMySQLTable_PROP
*>(const_cast<OMySQLTable
*>(this))->getArrayHelper(isNew() ? 1 : 0);
142 // -----------------------------------------------------------------------------
143 sdbcx::OCollection
* OMySQLTable::createColumns(const TStringVector
& _rNames
)
145 OMySQLColumns
* pColumns
= new OMySQLColumns(*this,sal_True
,m_aMutex
,_rNames
);
146 pColumns
->setParent(this);
149 // -----------------------------------------------------------------------------
150 sdbcx::OCollection
* OMySQLTable::createKeys(const TStringVector
& _rNames
)
152 return new OMySQLKeysHelper(this,m_aMutex
,_rNames
);
154 // -----------------------------------------------------------------------------
155 sdbcx::OCollection
* OMySQLTable::createIndexes(const TStringVector
& _rNames
)
157 return new OIndexesHelper(this,m_aMutex
,_rNames
);
159 //--------------------------------------------------------------------------
160 Sequence
< sal_Int8
> OMySQLTable::getUnoTunnelImplementationId()
162 static ::cppu::OImplementationId
* pId
= 0;
165 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
168 static ::cppu::OImplementationId aId
;
172 return pId
->getImplementationId();
175 // com::sun::star::lang::XUnoTunnel
176 //------------------------------------------------------------------
177 sal_Int64
OMySQLTable::getSomething( const Sequence
< sal_Int8
> & rId
) throw (RuntimeException
)
179 return (rId
.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId
.getConstArray(), 16 ) )
180 ? reinterpret_cast< sal_Int64
>( this )
181 : OTable_TYPEDEF::getSomething(rId
);
183 // -------------------------------------------------------------------------
185 void SAL_CALL
OMySQLTable::alterColumnByName( const ::rtl::OUString
& colName
, const Reference
< XPropertySet
>& descriptor
) throw(SQLException
, NoSuchElementException
, RuntimeException
)
187 ::osl::MutexGuard
aGuard(m_aMutex
);
190 ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper
.bDisposed
196 if ( m_pColumns
&& !m_pColumns
->hasByName(colName
) )
197 throw NoSuchElementException(colName
,*this);
202 // first we have to check what should be altered
203 Reference
<XPropertySet
> xProp
;
204 m_pColumns
->getByName(colName
) >>= xProp
;
205 // first check the types
206 sal_Int32 nOldType
= 0,nNewType
= 0,nOldPrec
= 0,nNewPrec
= 0,nOldScale
= 0,nNewScale
= 0;
208 ::dbtools::OPropertyMap
& rProp
= OMetaConnection::getPropMap();
209 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPE
)) >>= nOldType
;
210 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPE
)) >>= nNewType
;
211 // and precsions and scale
212 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_PRECISION
)) >>= nOldPrec
;
213 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_PRECISION
))>>= nNewPrec
;
214 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_SCALE
)) >>= nOldScale
;
215 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_SCALE
)) >>= nNewScale
;
216 // second: check the "is nullable" value
217 sal_Int32 nOldNullable
= 0,nNewNullable
= 0;
218 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_ISNULLABLE
)) >>= nOldNullable
;
219 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_ISNULLABLE
)) >>= nNewNullable
;
221 // check also the auto_increment
222 sal_Bool bOldAutoIncrement
= sal_False
,bAutoIncrement
= sal_False
;
223 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT
)) >>= bOldAutoIncrement
;
224 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT
)) >>= bAutoIncrement
;
225 bool bColumnNameChanged
= false;
227 if ( nOldType
!= nNewType
228 || nOldPrec
!= nNewPrec
229 || nOldScale
!= nNewScale
230 || nNewNullable
!= nOldNullable
231 || bOldAutoIncrement
!= bAutoIncrement
)
233 // special handling because they change dthe type names to distinguish
234 // if a column should be an auto_incmrement one
235 if ( bOldAutoIncrement
!= bAutoIncrement
)
237 ::rtl::OUString sTypeName
;
238 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPENAME
)) >>= sTypeName
;
240 static ::rtl::OUString
s_sAutoIncrement(RTL_CONSTASCII_USTRINGPARAM("auto_increment"));
241 if ( bAutoIncrement
)
243 if ( sTypeName
.indexOf(s_sAutoIncrement
) == -1 )
245 sTypeName
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" "));
246 sTypeName
+= s_sAutoIncrement
;
251 sal_Int32 nIndex
= 0;
252 if ( sTypeName
.getLength() && (nIndex
= sTypeName
.indexOf(s_sAutoIncrement
)) != -1 )
254 sTypeName
= sTypeName
.copy(0,nIndex
);
255 descriptor
->setPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPENAME
),makeAny(sTypeName
));
259 alterColumnType(nNewType
,colName
,descriptor
);
260 bColumnNameChanged
= true;
263 // third: check the default values
264 ::rtl::OUString sNewDefault
,sOldDefault
;
265 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_DEFAULTVALUE
)) >>= sOldDefault
;
266 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_DEFAULTVALUE
)) >>= sNewDefault
;
268 if(sOldDefault
.getLength())
270 dropDefaultValue(colName
);
271 if(sNewDefault
.getLength() && sOldDefault
!= sNewDefault
)
272 alterDefaultValue(sNewDefault
,colName
);
274 else if(!sOldDefault
.getLength() && sNewDefault
.getLength())
275 alterDefaultValue(sNewDefault
,colName
);
277 // now we should look if the name of the column changed
278 ::rtl::OUString sNewColumnName
;
279 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_NAME
)) >>= sNewColumnName
;
280 if ( !sNewColumnName
.equalsIgnoreAsciiCase(colName
) && !bColumnNameChanged
)
282 ::rtl::OUString sSql
= getAlterTableColumnPart();
283 sSql
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" CHANGE "));
284 const ::rtl::OUString sQuote
= getMetaData()->getIdentifierQuoteString( );
285 sSql
+= ::dbtools::quoteName(sQuote
,colName
);
286 sSql
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" "));
287 sSql
+= ::dbtools::createStandardColumnPart(descriptor
,getConnection(),getTypeCreatePattern());
288 executeStatement(sSql
);
290 m_pColumns
->refresh();
296 m_pColumns
->dropByName(colName
);
297 m_pColumns
->appendByDescriptor(descriptor
);
302 // -----------------------------------------------------------------------------
303 void OMySQLTable::alterColumnType(sal_Int32 nNewType
,const ::rtl::OUString
& _rColName
, const Reference
<XPropertySet
>& _xDescriptor
)
305 ::rtl::OUString sSql
= getAlterTableColumnPart();
306 sSql
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" CHANGE "));
307 const ::rtl::OUString sQuote
= getMetaData()->getIdentifierQuoteString( );
308 sSql
+= ::dbtools::quoteName(sQuote
,_rColName
);
309 sSql
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" "));
311 OColumn
* pColumn
= new OColumn(sal_True
);
312 Reference
<XPropertySet
> xProp
= pColumn
;
313 ::comphelper::copyProperties(_xDescriptor
,xProp
);
314 xProp
->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE
),makeAny(nNewType
));
316 sSql
+= ::dbtools::createStandardColumnPart(xProp
,getConnection(),getTypeCreatePattern());
317 executeStatement(sSql
);
319 // -----------------------------------------------------------------------------
320 ::rtl::OUString
OMySQLTable::getTypeCreatePattern() const
322 static const ::rtl::OUString
s_sCreatePattern(RTL_CONSTASCII_USTRINGPARAM("(M,D)"));
323 return s_sCreatePattern
;
325 // -----------------------------------------------------------------------------
326 void OMySQLTable::alterDefaultValue(const ::rtl::OUString
& _sNewDefault
,const ::rtl::OUString
& _rColName
)
328 ::rtl::OUString sSql
= getAlterTableColumnPart();
329 sSql
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ALTER "));
331 const ::rtl::OUString sQuote
= getMetaData()->getIdentifierQuoteString( );
332 sSql
+= ::dbtools::quoteName(sQuote
,_rColName
);
333 sSql
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" SET DEFAULT '")) + _sNewDefault
;
334 sSql
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("'"));
336 executeStatement(sSql
);
338 // -----------------------------------------------------------------------------
339 void OMySQLTable::dropDefaultValue(const ::rtl::OUString
& _rColName
)
341 ::rtl::OUString sSql
= getAlterTableColumnPart();
342 sSql
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ALTER "));
344 const ::rtl::OUString sQuote
= getMetaData()->getIdentifierQuoteString( );
345 sSql
+= ::dbtools::quoteName(sQuote
,_rColName
);
346 sSql
+= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" DROP DEFAULT"));
348 executeStatement(sSql
);
350 // -----------------------------------------------------------------------------
351 ::rtl::OUString
OMySQLTable::getAlterTableColumnPart()
353 ::rtl::OUString sSql
= ::rtl::OUString::createFromAscii("ALTER TABLE ");
354 const ::rtl::OUString sQuote
= getMetaData()->getIdentifierQuoteString( );
356 ::rtl::OUString
sComposedName(
357 ::dbtools::composeTableName( getMetaData(), m_CatalogName
, m_SchemaName
, m_Name
, sal_True
, ::dbtools::eInTableDefinitions
) );
358 sSql
+= sComposedName
;
362 // -----------------------------------------------------------------------------
363 void OMySQLTable::executeStatement(const ::rtl::OUString
& _rStatement
)
365 ::rtl::OUString sSQL
= _rStatement
;
366 if(sSQL
.lastIndexOf(',') == (sSQL
.getLength()-1))
367 sSQL
= sSQL
.replaceAt(sSQL
.getLength()-1,1,::rtl::OUString::createFromAscii(")"));
369 Reference
< XStatement
> xStmt
= getConnection()->createStatement( );
372 xStmt
->execute(sSQL
);
373 ::comphelper::disposeComponent(xStmt
);
376 // -----------------------------------------------------------------------------
377 ::rtl::OUString
OMySQLTable::getRenameStart() const
379 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RENAME TABLE "));