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 "hsqldb/HTable.hxx"
22 #include "hsqldb/HTables.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 "hsqldb/HCatalog.hxx"
40 #include "hsqldb/HColumns.hxx"
41 #include "TConnection.hxx"
43 #include <tools/diagnose_ex.h>
46 using namespace ::comphelper
;
47 using namespace connectivity::hsqldb
;
48 using namespace connectivity::sdbcx
;
49 using namespace connectivity
;
50 using namespace ::com::sun::star::uno
;
51 using namespace ::com::sun::star::beans
;
52 using namespace ::com::sun::star::sdbcx
;
53 using namespace ::com::sun::star::sdbc
;
54 using namespace ::com::sun::star::container
;
55 using namespace ::com::sun::star::lang
;
57 OHSQLTable::OHSQLTable( sdbcx::OCollection
* _pTables
,
58 const Reference
< XConnection
>& _xConnection
)
59 :OTableHelper(_pTables
,_xConnection
,true)
61 // we create a new table here, so we should have all the rights or ;-)
62 m_nPrivileges
= Privilege::DROP
|
63 Privilege::REFERENCE
|
74 OHSQLTable::OHSQLTable( sdbcx::OCollection
* _pTables
,
75 const Reference
< XConnection
>& _xConnection
,
78 const OUString
& Description
,
79 const OUString
& SchemaName
,
80 const OUString
& CatalogName
,
81 sal_Int32 _nPrivileges
82 ) : OTableHelper( _pTables
,
90 , m_nPrivileges(_nPrivileges
)
95 void OHSQLTable::construct()
97 OTableHelper::construct();
99 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRIVILEGES
), PROPERTY_ID_PRIVILEGES
,PropertyAttribute::READONLY
,&m_nPrivileges
, cppu::UnoType
<decltype(m_nPrivileges
)>::get());
102 ::cppu::IPropertyArrayHelper
* OHSQLTable::createArrayHelper( sal_Int32
/*_nId*/ ) const
104 return doCreateArrayHelper();
107 ::cppu::IPropertyArrayHelper
& OHSQLTable::getInfoHelper()
109 return *static_cast<OHSQLTable_PROP
*>(this)->getArrayHelper(isNew() ? 1 : 0);
112 sdbcx::OCollection
* OHSQLTable::createColumns(const TStringVector
& _rNames
)
114 OHSQLColumns
* pColumns
= new OHSQLColumns(*this,m_aMutex
,_rNames
);
115 pColumns
->setParent(this);
119 sdbcx::OCollection
* OHSQLTable::createKeys(const TStringVector
& _rNames
)
121 return new OKeysHelper(this,m_aMutex
,_rNames
);
124 sdbcx::OCollection
* OHSQLTable::createIndexes(const TStringVector
& _rNames
)
126 return new OIndexesHelper(this,m_aMutex
,_rNames
);
129 Sequence
< sal_Int8
> OHSQLTable::getUnoTunnelImplementationId()
131 static ::cppu::OImplementationId
* pId
= nullptr;
134 ::osl::MutexGuard
aGuard( ::osl::Mutex::getGlobalMutex() );
137 static ::cppu::OImplementationId aId
;
141 return pId
->getImplementationId();
144 // css::lang::XUnoTunnel
146 sal_Int64
OHSQLTable::getSomething( const Sequence
< sal_Int8
> & rId
) throw (RuntimeException
, std::exception
)
148 return (rId
.getLength() == 16 && 0 == memcmp(getUnoTunnelImplementationId().getConstArray(), rId
.getConstArray(), 16 ) )
149 ? reinterpret_cast< sal_Int64
>( this )
150 : OTable_TYPEDEF::getSomething(rId
);
154 void SAL_CALL
OHSQLTable::alterColumnByName( const OUString
& colName
, const Reference
< XPropertySet
>& descriptor
) throw(SQLException
, NoSuchElementException
, RuntimeException
, std::exception
)
156 ::osl::MutexGuard
aGuard(m_aMutex
);
159 ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper
.bDisposed
165 if ( !m_pColumns
|| !m_pColumns
->hasByName(colName
) )
166 throw NoSuchElementException(colName
,*this);
171 // first we have to check what should be altered
172 Reference
<XPropertySet
> xProp
;
173 m_pColumns
->getByName(colName
) >>= xProp
;
174 // first check the types
175 sal_Int32 nOldType
= 0,nNewType
= 0,nOldPrec
= 0,nNewPrec
= 0,nOldScale
= 0,nNewScale
= 0;
176 OUString sOldTypeName
, sNewTypeName
;
178 ::dbtools::OPropertyMap
& rProp
= OMetaConnection::getPropMap();
181 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPE
)) >>= nOldType
;
182 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPE
)) >>= nNewType
;
183 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPENAME
)) >>= sOldTypeName
;
184 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPENAME
))>>= sNewTypeName
;
186 // and precsions and scale
187 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_PRECISION
)) >>= nOldPrec
;
188 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_PRECISION
))>>= nNewPrec
;
189 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_SCALE
)) >>= nOldScale
;
190 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_SCALE
)) >>= nNewScale
;
192 // second: check the "is nullable" value
193 sal_Int32 nOldNullable
= 0,nNewNullable
= 0;
194 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_ISNULLABLE
)) >>= nOldNullable
;
195 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_ISNULLABLE
)) >>= nNewNullable
;
197 // check also the auto_increment
198 bool bOldAutoIncrement
= false,bAutoIncrement
= false;
199 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT
)) >>= bOldAutoIncrement
;
200 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT
)) >>= bAutoIncrement
;
202 // now we should look if the name of the column changed
203 OUString sNewColumnName
;
204 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_NAME
)) >>= sNewColumnName
;
205 if ( !sNewColumnName
.equals(colName
) )
207 const OUString sQuote
= getMetaData()->getIdentifierQuoteString( );
209 OUString sSql
= getAlterTableColumnPart() +
211 ::dbtools::quoteName(sQuote
,colName
) +
213 ::dbtools::quoteName(sQuote
,sNewColumnName
);
215 executeStatement(sSql
);
218 if ( nOldType
!= nNewType
219 || sOldTypeName
!= sNewTypeName
220 || nOldPrec
!= nNewPrec
221 || nOldScale
!= nNewScale
222 || nNewNullable
!= nOldNullable
223 || bOldAutoIncrement
!= bAutoIncrement
)
225 // special handling because they change the type names to distinguish
226 // if a column should be an auto_incmrement one
227 if ( bOldAutoIncrement
!= bAutoIncrement
)
229 /// TODO: insert special handling for auto increment "IDENTITY" and primary key
231 alterColumnType(nNewType
,sNewColumnName
,descriptor
);
234 // third: check the default values
235 OUString sNewDefault
,sOldDefault
;
236 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_DEFAULTVALUE
)) >>= sOldDefault
;
237 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_DEFAULTVALUE
)) >>= sNewDefault
;
239 if(!sOldDefault
.isEmpty())
241 dropDefaultValue(colName
);
242 if(!sNewDefault
.isEmpty() && sOldDefault
!= sNewDefault
)
243 alterDefaultValue(sNewDefault
,sNewColumnName
);
245 else if(sOldDefault
.isEmpty() && !sNewDefault
.isEmpty())
246 alterDefaultValue(sNewDefault
,sNewColumnName
);
248 m_pColumns
->refresh();
254 m_pColumns
->dropByName(colName
);
255 m_pColumns
->appendByDescriptor(descriptor
);
261 void OHSQLTable::alterColumnType(sal_Int32 nNewType
,const OUString
& _rColName
, const Reference
<XPropertySet
>& _xDescriptor
)
263 OUString sSql
= getAlterTableColumnPart() + " ALTER COLUMN ";
264 #if OSL_DEBUG_LEVEL > 0
267 OUString sDescriptorName
;
268 OSL_ENSURE( _xDescriptor
.is()
269 && ( _xDescriptor
->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_NAME
) ) >>= sDescriptorName
)
270 && ( sDescriptorName
== _rColName
),
271 "OHSQLTable::alterColumnType: unexpected column name!" );
273 catch( const Exception
& )
275 DBG_UNHANDLED_EXCEPTION();
281 OHSQLColumn
* pColumn
= new OHSQLColumn
;
282 Reference
<XPropertySet
> xProp
= pColumn
;
283 ::comphelper::copyProperties(_xDescriptor
,xProp
);
284 xProp
->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE
),makeAny(nNewType
));
286 sSql
+= ::dbtools::createStandardColumnPart(xProp
,getConnection());
287 executeStatement(sSql
);
290 void OHSQLTable::alterDefaultValue(const OUString
& _sNewDefault
,const OUString
& _rColName
)
292 const OUString sQuote
= getMetaData()->getIdentifierQuoteString( );
293 OUString sSql
= getAlterTableColumnPart() +
295 ::dbtools::quoteName(sQuote
,_rColName
) +
296 " SET DEFAULT '" + _sNewDefault
+ "'";
298 executeStatement(sSql
);
301 void OHSQLTable::dropDefaultValue(const OUString
& _rColName
)
303 const OUString sQuote
= getMetaData()->getIdentifierQuoteString( );
304 OUString sSql
= getAlterTableColumnPart() +
306 ::dbtools::quoteName(sQuote
,_rColName
) +
309 executeStatement(sSql
);
312 OUString
OHSQLTable::getAlterTableColumnPart()
314 OUString
sSql( "ALTER TABLE " );
316 OUString
sComposedName( ::dbtools::composeTableName( getMetaData(), m_CatalogName
, m_SchemaName
, m_Name
, true, ::dbtools::EComposeRule::InTableDefinitions
) );
317 sSql
+= sComposedName
;
322 void OHSQLTable::executeStatement(const OUString
& _rStatement
)
324 OUString sSQL
= _rStatement
;
325 if(sSQL
.endsWith(","))
326 sSQL
= sSQL
.replaceAt(sSQL
.getLength()-1, 1, ")");
328 Reference
< XStatement
> xStmt
= getConnection()->createStatement( );
331 try { xStmt
->execute(sSQL
); }
332 catch( const Exception
& )
334 ::comphelper::disposeComponent(xStmt
);
337 ::comphelper::disposeComponent(xStmt
);
341 Sequence
< Type
> SAL_CALL
OHSQLTable::getTypes( ) throw(RuntimeException
, std::exception
)
343 if ( m_Type
== "VIEW" )
345 Sequence
< Type
> aTypes
= OTableHelper::getTypes();
346 ::std::vector
<Type
> aOwnTypes
;
347 aOwnTypes
.reserve(aTypes
.getLength());
348 const Type
* pIter
= aTypes
.getConstArray();
349 const Type
* pEnd
= pIter
+ aTypes
.getLength();
350 for(;pIter
!= pEnd
;++pIter
)
352 if( *pIter
!= cppu::UnoType
<XRename
>::get())
354 aOwnTypes
.push_back(*pIter
);
357 return Sequence
< Type
>(aOwnTypes
.data(), aOwnTypes
.size());
359 return OTableHelper::getTypes();
363 void SAL_CALL
OHSQLTable::rename( const OUString
& newName
) throw(SQLException
, ElementExistException
, RuntimeException
, std::exception
)
365 ::osl::MutexGuard
aGuard(m_aMutex
);
368 ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper
.bDisposed
376 OUString sSql
= "ALTER ";
377 if ( m_Type
== "VIEW" )
382 OUString sCatalog
,sSchema
,sTable
;
383 ::dbtools::qualifiedNameComponents(getMetaData(),newName
,sCatalog
,sSchema
,sTable
,::dbtools::EComposeRule::InDataManipulation
);
386 ::dbtools::composeTableName( getMetaData(), m_CatalogName
, m_SchemaName
, m_Name
, true, ::dbtools::EComposeRule::InDataManipulation
)
388 + ::dbtools::composeTableName( getMetaData(), sCatalog
, sSchema
, sTable
, true, ::dbtools::EComposeRule::InDataManipulation
);
390 executeStatement(sSql
);
392 ::connectivity::OTable_TYPEDEF::rename(newName
);
395 ::dbtools::qualifiedNameComponents(getMetaData(),newName
,m_CatalogName
,m_SchemaName
,m_Name
,::dbtools::EComposeRule::InTableDefinitions
);
399 Any SAL_CALL
OHSQLTable::queryInterface( const Type
& rType
) throw(RuntimeException
, std::exception
)
401 if( m_Type
== "VIEW" && rType
== cppu::UnoType
<XRename
>::get())
404 return OTableHelper::queryInterface(rType
);
408 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */