Update ooo320-m1
[ooovba.git] / connectivity / source / drivers / hsqldb / HTable.cxx
blob8e6fc34b2c9b6b896cfb91ee02b0d92116e6f867
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: HTable.cxx,v $
10 * $Revision: 1.13 $
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 "hsqldb/HTable.hxx"
34 #include "hsqldb/HTables.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 "hsqldb/HCatalog.hxx"
52 #include "hsqldb/HColumns.hxx"
53 #include "TConnection.hxx"
55 #include <tools/diagnose_ex.h>
58 using namespace ::comphelper;
59 using namespace connectivity::hsqldb;
60 using namespace connectivity::sdbcx;
61 using namespace connectivity;
62 using namespace ::com::sun::star::uno;
63 using namespace ::com::sun::star::beans;
64 using namespace ::com::sun::star::sdbcx;
65 using namespace ::com::sun::star::sdbc;
66 using namespace ::com::sun::star::container;
67 using namespace ::com::sun::star::lang;
69 OHSQLTable::OHSQLTable( sdbcx::OCollection* _pTables,
70 const Reference< XConnection >& _xConnection)
71 :OTableHelper(_pTables,_xConnection,sal_True)
73 // we create a new table here, so we should have all the rights or ;-)
74 m_nPrivileges = Privilege::DROP |
75 Privilege::REFERENCE |
76 Privilege::ALTER |
77 Privilege::CREATE |
78 Privilege::READ |
79 Privilege::DELETE |
80 Privilege::UPDATE |
81 Privilege::INSERT |
82 Privilege::SELECT;
83 construct();
85 // -------------------------------------------------------------------------
86 OHSQLTable::OHSQLTable( sdbcx::OCollection* _pTables,
87 const Reference< XConnection >& _xConnection,
88 const ::rtl::OUString& _Name,
89 const ::rtl::OUString& _Type,
90 const ::rtl::OUString& _Description ,
91 const ::rtl::OUString& _SchemaName,
92 const ::rtl::OUString& _CatalogName,
93 sal_Int32 _nPrivileges
94 ) : OTableHelper( _pTables,
95 _xConnection,
96 sal_True,
97 _Name,
98 _Type,
99 _Description,
100 _SchemaName,
101 _CatalogName)
102 , m_nPrivileges(_nPrivileges)
104 construct();
106 // -------------------------------------------------------------------------
107 void OHSQLTable::construct()
109 OTableHelper::construct();
110 if ( !isNew() )
111 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRIVILEGES), PROPERTY_ID_PRIVILEGES,PropertyAttribute::READONLY,&m_nPrivileges, ::getCppuType(&m_nPrivileges));
113 // -----------------------------------------------------------------------------
114 ::cppu::IPropertyArrayHelper* OHSQLTable::createArrayHelper( sal_Int32 /*_nId*/ ) const
116 return doCreateArrayHelper();
118 // -------------------------------------------------------------------------
119 ::cppu::IPropertyArrayHelper & OHSQLTable::getInfoHelper()
121 return *static_cast<OHSQLTable_PROP*>(const_cast<OHSQLTable*>(this))->getArrayHelper(isNew() ? 1 : 0);
123 // -----------------------------------------------------------------------------
124 sdbcx::OCollection* OHSQLTable::createColumns(const TStringVector& _rNames)
126 OHSQLColumns* pColumns = new OHSQLColumns(*this,sal_True,m_aMutex,_rNames);
127 pColumns->setParent(this);
128 return pColumns;
130 // -----------------------------------------------------------------------------
131 sdbcx::OCollection* OHSQLTable::createKeys(const TStringVector& _rNames)
133 return new OKeysHelper(this,m_aMutex,_rNames);
135 // -----------------------------------------------------------------------------
136 sdbcx::OCollection* OHSQLTable::createIndexes(const TStringVector& _rNames)
138 return new OIndexesHelper(this,m_aMutex,_rNames);
140 //--------------------------------------------------------------------------
141 Sequence< sal_Int8 > OHSQLTable::getUnoTunnelImplementationId()
143 static ::cppu::OImplementationId * pId = 0;
144 if (! pId)
146 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
147 if (! pId)
149 static ::cppu::OImplementationId aId;
150 pId = &aId;
153 return pId->getImplementationId();
156 // com::sun::star::lang::XUnoTunnel
157 //------------------------------------------------------------------
158 sal_Int64 OHSQLTable::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException)
160 return (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) )
161 ? reinterpret_cast< sal_Int64 >( this )
162 : OTable_TYPEDEF::getSomething(rId);
164 // -------------------------------------------------------------------------
165 // XAlterTable
166 void SAL_CALL OHSQLTable::alterColumnByName( const ::rtl::OUString& colName, const Reference< XPropertySet >& descriptor ) throw(SQLException, NoSuchElementException, RuntimeException)
168 ::osl::MutexGuard aGuard(m_aMutex);
169 checkDisposed(
170 #ifdef GCC
171 ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper.bDisposed
172 #else
173 rBHelper.bDisposed
174 #endif
177 if ( m_pColumns && !m_pColumns->hasByName(colName) )
178 throw NoSuchElementException(colName,*this);
181 if ( !isNew() )
183 // first we have to check what should be altered
184 Reference<XPropertySet> xProp;
185 m_pColumns->getByName(colName) >>= xProp;
186 // first check the types
187 sal_Int32 nOldType = 0,nNewType = 0,nOldPrec = 0,nNewPrec = 0,nOldScale = 0,nNewScale = 0;
188 ::rtl::OUString sOldTypeName, sNewTypeName;
190 ::dbtools::OPropertyMap& rProp = OMetaConnection::getPropMap();
192 // type/typename
193 xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPE)) >>= nOldType;
194 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPE)) >>= nNewType;
195 xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPENAME)) >>= sOldTypeName;
196 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_TYPENAME))>>= sNewTypeName;
198 // and precsions and scale
199 xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_PRECISION)) >>= nOldPrec;
200 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_PRECISION))>>= nNewPrec;
201 xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_SCALE)) >>= nOldScale;
202 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;
214 // now we should look if the name of the column changed
215 ::rtl::OUString sNewColumnName;
216 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_NAME)) >>= sNewColumnName;
217 if ( !sNewColumnName.equalsIgnoreAsciiCase(colName) )
219 const ::rtl::OUString sQuote = getMetaData()->getIdentifierQuoteString( );
221 ::rtl::OUString sSql = getAlterTableColumnPart();
222 sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ALTER COLUMN "));
223 sSql += ::dbtools::quoteName(sQuote,colName);
225 sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" RENAME TO "));
226 sSql += ::dbtools::quoteName(sQuote,sNewColumnName);
228 executeStatement(sSql);
231 if ( nOldType != nNewType
232 || sOldTypeName != sNewTypeName
233 || nOldPrec != nNewPrec
234 || nOldScale != nNewScale
235 || nNewNullable != nOldNullable
236 || bOldAutoIncrement != bAutoIncrement )
238 // special handling because they change the type names to distinguish
239 // if a column should be an auto_incmrement one
240 if ( bOldAutoIncrement != bAutoIncrement )
242 /// TODO: insert special handling for auto increment "IDENTITY" and primary key
244 alterColumnType(nNewType,sNewColumnName,descriptor);
247 // third: check the default values
248 ::rtl::OUString sNewDefault,sOldDefault;
249 xProp->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_DEFAULTVALUE)) >>= sOldDefault;
250 descriptor->getPropertyValue(rProp.getNameByIndex(PROPERTY_ID_DEFAULTVALUE)) >>= sNewDefault;
252 if(sOldDefault.getLength())
254 dropDefaultValue(colName);
255 if(sNewDefault.getLength() && sOldDefault != sNewDefault)
256 alterDefaultValue(sNewDefault,sNewColumnName);
258 else if(!sOldDefault.getLength() && sNewDefault.getLength())
259 alterDefaultValue(sNewDefault,sNewColumnName);
261 m_pColumns->refresh();
263 else
265 if(m_pColumns)
267 m_pColumns->dropByName(colName);
268 m_pColumns->appendByDescriptor(descriptor);
273 // -----------------------------------------------------------------------------
274 void OHSQLTable::alterColumnType(sal_Int32 nNewType,const ::rtl::OUString& _rColName, const Reference<XPropertySet>& _xDescriptor)
276 ::rtl::OUString sSql = getAlterTableColumnPart();
278 sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ALTER COLUMN "));
279 #if OSL_DEBUG_LEVEL > 0
282 ::rtl::OUString sDescriptorName;
283 OSL_ENSURE( _xDescriptor.is()
284 && ( _xDescriptor->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_NAME ) ) >>= sDescriptorName )
285 && ( sDescriptorName == _rColName ),
286 "OHSQLTable::alterColumnType: unexpected column name!" );
288 catch( const Exception& )
290 DBG_UNHANDLED_EXCEPTION();
292 #else
293 (void)_rColName;
294 #endif
296 OHSQLColumn* pColumn = new OHSQLColumn(sal_True);
297 Reference<XPropertySet> xProp = pColumn;
298 ::comphelper::copyProperties(_xDescriptor,xProp);
299 xProp->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE),makeAny(nNewType));
301 sSql += ::dbtools::createStandardColumnPart(xProp,getConnection());
302 executeStatement(sSql);
304 // -----------------------------------------------------------------------------
305 void OHSQLTable::alterDefaultValue(const ::rtl::OUString& _sNewDefault,const ::rtl::OUString& _rColName)
307 ::rtl::OUString sSql = getAlterTableColumnPart();
308 sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ALTER COLUMN "));
310 const ::rtl::OUString sQuote = getMetaData()->getIdentifierQuoteString( );
311 sSql += ::dbtools::quoteName(sQuote,_rColName);
312 sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" SET DEFAULT '")) + _sNewDefault;
313 sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("'"));
315 executeStatement(sSql);
317 // -----------------------------------------------------------------------------
318 void OHSQLTable::dropDefaultValue(const ::rtl::OUString& _rColName)
320 ::rtl::OUString sSql = getAlterTableColumnPart();
321 sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ALTER COLUMN "));
323 const ::rtl::OUString sQuote = getMetaData()->getIdentifierQuoteString( );
324 sSql += ::dbtools::quoteName(sQuote,_rColName);
325 sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" DROP DEFAULT"));
327 executeStatement(sSql);
329 // -----------------------------------------------------------------------------
330 ::rtl::OUString OHSQLTable::getAlterTableColumnPart()
332 ::rtl::OUString sSql = ::rtl::OUString::createFromAscii("ALTER TABLE ");
333 const ::rtl::OUString sQuote = getMetaData()->getIdentifierQuoteString( );
335 ::rtl::OUString sComposedName( ::dbtools::composeTableName( getMetaData(), m_CatalogName, m_SchemaName, m_Name, sal_True, ::dbtools::eInTableDefinitions ) );
336 sSql += sComposedName;
338 return sSql;
340 // -----------------------------------------------------------------------------
341 void OHSQLTable::executeStatement(const ::rtl::OUString& _rStatement )
343 ::rtl::OUString sSQL = _rStatement;
344 if(sSQL.lastIndexOf(',') == (sSQL.getLength()-1))
345 sSQL = sSQL.replaceAt(sSQL.getLength()-1,1,::rtl::OUString::createFromAscii(")"));
347 Reference< XStatement > xStmt = getConnection()->createStatement( );
348 if ( xStmt.is() )
350 try { xStmt->execute(sSQL); }
351 catch( const Exception& )
353 ::comphelper::disposeComponent(xStmt);
354 throw;
356 ::comphelper::disposeComponent(xStmt);
359 // -----------------------------------------------------------------------------
360 Sequence< Type > SAL_CALL OHSQLTable::getTypes( ) throw(RuntimeException)
362 if ( ! m_Type.compareToAscii("VIEW") )
364 Sequence< Type > aTypes = OTableHelper::getTypes();
365 ::std::vector<Type> aOwnTypes;
366 aOwnTypes.reserve(aTypes.getLength());
367 const Type* pIter = aTypes.getConstArray();
368 const Type* pEnd = pIter + aTypes.getLength();
369 for(;pIter != pEnd;++pIter)
371 if( *pIter != ::getCppuType((const Reference<XRename>*)0) )
373 aOwnTypes.push_back(*pIter);
376 Type *pTypes = aOwnTypes.empty() ? 0 : &aOwnTypes[0];
377 return Sequence< Type >(pTypes, aOwnTypes.size());
379 return OTableHelper::getTypes();
381 // -------------------------------------------------------------------------
382 // XRename
383 void SAL_CALL OHSQLTable::rename( const ::rtl::OUString& newName ) throw(SQLException, ElementExistException, RuntimeException)
385 ::osl::MutexGuard aGuard(m_aMutex);
386 checkDisposed(
387 #ifdef GCC
388 ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper.bDisposed
389 #else
390 rBHelper.bDisposed
391 #endif
394 if(!isNew())
396 ::rtl::OUString sSql = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ALTER "));
397 if ( m_Type == ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("VIEW")) )
398 sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" VIEW "));
399 else
400 sSql += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" TABLE "));
402 ::rtl::OUString sQuote = getMetaData()->getIdentifierQuoteString( );
404 ::rtl::OUString sCatalog,sSchema,sTable;
405 ::dbtools::qualifiedNameComponents(getMetaData(),newName,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation);
407 ::rtl::OUString sComposedName(
408 ::dbtools::composeTableName( getMetaData(), m_CatalogName, m_SchemaName, m_Name, sal_True, ::dbtools::eInDataManipulation ) );
409 sSql += sComposedName
410 + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" RENAME TO "));
411 sSql += ::dbtools::composeTableName( getMetaData(), sCatalog, sSchema, sTable, sal_True, ::dbtools::eInDataManipulation );
413 executeStatement(sSql);
415 ::connectivity::OTable_TYPEDEF::rename(newName);
417 else
418 ::dbtools::qualifiedNameComponents(getMetaData(),newName,m_CatalogName,m_SchemaName,m_Name,::dbtools::eInTableDefinitions);
421 // -------------------------------------------------------------------------
422 Any SAL_CALL OHSQLTable::queryInterface( const Type & rType ) throw(RuntimeException)
424 if( !m_Type.compareToAscii("VIEW") && rType == ::getCppuType((const Reference<XRename>*)0) )
425 return Any();
427 return OTableHelper::queryInterface(rType);
429 // -------------------------------------------------------------------------