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: HTable.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 "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
|
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
,
102 , m_nPrivileges(_nPrivileges
)
106 // -------------------------------------------------------------------------
107 void OHSQLTable::construct()
109 OTableHelper::construct();
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);
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;
146 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
149 static ::cppu::OImplementationId 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 // -------------------------------------------------------------------------
166 void SAL_CALL
OHSQLTable::alterColumnByName( const ::rtl::OUString
& colName
, const Reference
< XPropertySet
>& descriptor
) throw(SQLException
, NoSuchElementException
, RuntimeException
)
168 ::osl::MutexGuard
aGuard(m_aMutex
);
171 ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper
.bDisposed
177 if ( m_pColumns
&& !m_pColumns
->hasByName(colName
) )
178 throw NoSuchElementException(colName
,*this);
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();
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();
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();
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
;
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( );
350 try { xStmt
->execute(sSQL
); }
351 catch( const Exception
& )
353 ::comphelper::disposeComponent(xStmt
);
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 // -------------------------------------------------------------------------
383 void SAL_CALL
OHSQLTable::rename( const ::rtl::OUString
& newName
) throw(SQLException
, ElementExistException
, RuntimeException
)
385 ::osl::MutexGuard
aGuard(m_aMutex
);
388 ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper
.bDisposed
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 "));
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
);
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) )
427 return OTableHelper::queryInterface(rType
);
429 // -------------------------------------------------------------------------