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 .
20 #include <hsqldb/HTable.hxx>
21 #include <cppuhelper/typeprovider.hxx>
22 #include <com/sun/star/beans/PropertyAttribute.hpp>
23 #include <com/sun/star/sdbcx/Privilege.hpp>
24 #include <comphelper/property.hxx>
25 #include <comphelper/servicehelper.hxx>
26 #include <comphelper/types.hxx>
27 #include <connectivity/dbtools.hxx>
28 #include <connectivity/TKeys.hxx>
29 #include <connectivity/TIndexes.hxx>
30 #include <hsqldb/HColumns.hxx>
31 #include <TConnection.hxx>
33 #include <tools/diagnose_ex.h>
36 using namespace ::comphelper
;
37 using namespace connectivity::hsqldb
;
38 using namespace connectivity::sdbcx
;
39 using namespace connectivity
;
40 using namespace ::com::sun::star::uno
;
41 using namespace ::com::sun::star::beans
;
42 using namespace ::com::sun::star::sdbcx
;
43 using namespace ::com::sun::star::sdbc
;
44 using namespace ::com::sun::star::container
;
45 using namespace ::com::sun::star::lang
;
47 OHSQLTable::OHSQLTable( sdbcx::OCollection
* _pTables
,
48 const Reference
< XConnection
>& _xConnection
)
49 :OTableHelper(_pTables
,_xConnection
,true)
51 // we create a new table here, so we should have all the rights or ;-)
52 m_nPrivileges
= Privilege::DROP
|
53 Privilege::REFERENCE
|
64 OHSQLTable::OHSQLTable( sdbcx::OCollection
* _pTables
,
65 const Reference
< XConnection
>& _xConnection
,
68 const OUString
& Description
,
69 const OUString
& SchemaName
,
70 const OUString
& CatalogName
,
71 sal_Int32 _nPrivileges
72 ) : OTableHelper( _pTables
,
80 , m_nPrivileges(_nPrivileges
)
85 void OHSQLTable::construct()
87 OTableHelper::construct();
89 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRIVILEGES
), PROPERTY_ID_PRIVILEGES
,PropertyAttribute::READONLY
,&m_nPrivileges
, cppu::UnoType
<decltype(m_nPrivileges
)>::get());
92 ::cppu::IPropertyArrayHelper
* OHSQLTable::createArrayHelper( sal_Int32
/*_nId*/ ) const
94 return doCreateArrayHelper();
97 ::cppu::IPropertyArrayHelper
& OHSQLTable::getInfoHelper()
99 return *static_cast<OHSQLTable_PROP
*>(this)->getArrayHelper(isNew() ? 1 : 0);
102 sdbcx::OCollection
* OHSQLTable::createColumns(const ::std::vector
< OUString
>& _rNames
)
104 OHSQLColumns
* pColumns
= new OHSQLColumns(*this,m_aMutex
,_rNames
);
105 pColumns
->setParent(this);
109 sdbcx::OCollection
* OHSQLTable::createKeys(const ::std::vector
< OUString
>& _rNames
)
111 return new OKeysHelper(this,m_aMutex
,_rNames
);
114 sdbcx::OCollection
* OHSQLTable::createIndexes(const ::std::vector
< OUString
>& _rNames
)
116 return new OIndexesHelper(this,m_aMutex
,_rNames
);
119 Sequence
< sal_Int8
> OHSQLTable::getUnoTunnelId()
121 static ::cppu::OImplementationId implId
;
123 return implId
.getImplementationId();
126 // css::lang::XUnoTunnel
128 sal_Int64
OHSQLTable::getSomething( const Sequence
< sal_Int8
> & rId
)
130 return (isUnoTunnelId
<OHSQLTable
>(rId
))
131 ? reinterpret_cast< sal_Int64
>( this )
132 : OTable_TYPEDEF::getSomething(rId
);
136 void SAL_CALL
OHSQLTable::alterColumnByName( const OUString
& colName
, const Reference
< XPropertySet
>& descriptor
)
138 ::osl::MutexGuard
aGuard(m_aMutex
);
141 ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper
.bDisposed
147 if ( !m_xColumns
|| !m_xColumns
->hasByName(colName
) )
148 throw NoSuchElementException(colName
,*this);
153 // first we have to check what should be altered
154 Reference
<XPropertySet
> xProp
;
155 m_xColumns
->getByName(colName
) >>= xProp
;
156 // first check the types
157 sal_Int32 nOldType
= 0,nNewType
= 0,nOldPrec
= 0,nNewPrec
= 0,nOldScale
= 0,nNewScale
= 0;
158 OUString sOldTypeName
, sNewTypeName
;
160 ::dbtools::OPropertyMap
& rProp
= OMetaConnection::getPropMap();
163 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPE
)) >>= nOldType
;
164 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPE
)) >>= nNewType
;
165 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPENAME
)) >>= sOldTypeName
;
166 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPENAME
))>>= sNewTypeName
;
168 // and precision and scale
169 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_PRECISION
)) >>= nOldPrec
;
170 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_PRECISION
))>>= nNewPrec
;
171 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_SCALE
)) >>= nOldScale
;
172 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_SCALE
)) >>= nNewScale
;
174 // second: check the "is nullable" value
175 sal_Int32 nOldNullable
= 0,nNewNullable
= 0;
176 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_ISNULLABLE
)) >>= nOldNullable
;
177 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_ISNULLABLE
)) >>= nNewNullable
;
179 // check also the auto_increment
180 bool bOldAutoIncrement
= false,bAutoIncrement
= false;
181 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT
)) >>= bOldAutoIncrement
;
182 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT
)) >>= bAutoIncrement
;
184 // now we should look if the name of the column changed
185 OUString sNewColumnName
;
186 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_NAME
)) >>= sNewColumnName
;
187 if ( sNewColumnName
!= colName
)
189 const OUString sQuote
= getMetaData()->getIdentifierQuoteString( );
191 OUString sSql
= getAlterTableColumnPart() +
193 ::dbtools::quoteName(sQuote
,colName
) +
195 ::dbtools::quoteName(sQuote
,sNewColumnName
);
197 executeStatement(sSql
);
200 if ( nOldType
!= nNewType
201 || sOldTypeName
!= sNewTypeName
202 || nOldPrec
!= nNewPrec
203 || nOldScale
!= nNewScale
204 || nNewNullable
!= nOldNullable
205 || bOldAutoIncrement
!= bAutoIncrement
)
207 // special handling because they change the type names to distinguish
208 // if a column should be an auto_increment one
209 if ( bOldAutoIncrement
!= bAutoIncrement
)
211 /// TODO: insert special handling for auto increment "IDENTITY" and primary key
213 alterColumnType(nNewType
,sNewColumnName
,descriptor
);
216 // third: check the default values
217 OUString sNewDefault
,sOldDefault
;
218 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_DEFAULTVALUE
)) >>= sOldDefault
;
219 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_DEFAULTVALUE
)) >>= sNewDefault
;
221 if(!sOldDefault
.isEmpty())
223 dropDefaultValue(colName
);
224 if(!sNewDefault
.isEmpty() && sOldDefault
!= sNewDefault
)
225 alterDefaultValue(sNewDefault
,sNewColumnName
);
227 else if(sOldDefault
.isEmpty() && !sNewDefault
.isEmpty())
228 alterDefaultValue(sNewDefault
,sNewColumnName
);
230 m_xColumns
->refresh();
236 m_xColumns
->dropByName(colName
);
237 m_xColumns
->appendByDescriptor(descriptor
);
243 void OHSQLTable::alterColumnType(sal_Int32 nNewType
,const OUString
& _rColName
, const Reference
<XPropertySet
>& _xDescriptor
)
245 OUString sSql
= getAlterTableColumnPart() + " ALTER COLUMN ";
246 #if OSL_DEBUG_LEVEL > 0
249 OUString sDescriptorName
;
250 OSL_ENSURE( _xDescriptor
.is()
251 && ( _xDescriptor
->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_NAME
) ) >>= sDescriptorName
)
252 && ( sDescriptorName
== _rColName
),
253 "OHSQLTable::alterColumnType: unexpected column name!" );
255 catch( const Exception
& )
257 DBG_UNHANDLED_EXCEPTION("connectivity.hsqldb");
263 rtl::Reference
<OHSQLColumn
> pColumn
= new OHSQLColumn
;
264 ::comphelper::copyProperties(_xDescriptor
,pColumn
);
265 pColumn
->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE
),makeAny(nNewType
));
267 sSql
+= ::dbtools::createStandardColumnPart(pColumn
,getConnection());
268 executeStatement(sSql
);
271 void OHSQLTable::alterDefaultValue(std::u16string_view _sNewDefault
,const OUString
& _rColName
)
273 const OUString sQuote
= getMetaData()->getIdentifierQuoteString( );
274 OUString sSql
= getAlterTableColumnPart() +
276 ::dbtools::quoteName(sQuote
,_rColName
) +
277 " SET DEFAULT '" + _sNewDefault
+ "'";
279 executeStatement(sSql
);
282 void OHSQLTable::dropDefaultValue(const OUString
& _rColName
)
284 const OUString sQuote
= getMetaData()->getIdentifierQuoteString( );
285 OUString sSql
= getAlterTableColumnPart() +
287 ::dbtools::quoteName(sQuote
,_rColName
) +
290 executeStatement(sSql
);
293 OUString
OHSQLTable::getAlterTableColumnPart() const
295 OUString
sSql( "ALTER TABLE " );
297 OUString
sComposedName( ::dbtools::composeTableName( getMetaData(), m_CatalogName
, m_SchemaName
, m_Name
, true, ::dbtools::EComposeRule::InTableDefinitions
) );
298 sSql
+= sComposedName
;
303 void OHSQLTable::executeStatement(const OUString
& _rStatement
)
305 OUString sSQL
= _rStatement
;
306 if(sSQL
.endsWith(","))
307 sSQL
= sSQL
.replaceAt(sSQL
.getLength()-1, 1, ")");
309 Reference
< XStatement
> xStmt
= getConnection()->createStatement( );
312 try { xStmt
->execute(sSQL
); }
313 catch( const Exception
& )
315 ::comphelper::disposeComponent(xStmt
);
318 ::comphelper::disposeComponent(xStmt
);
322 Sequence
< Type
> SAL_CALL
OHSQLTable::getTypes( )
324 if ( m_Type
== "VIEW" )
326 Sequence
< Type
> aTypes
= OTableHelper::getTypes();
327 std::vector
<Type
> aOwnTypes
;
328 aOwnTypes
.reserve(aTypes
.getLength());
329 const Type
* pIter
= aTypes
.getConstArray();
330 const Type
* pEnd
= pIter
+ aTypes
.getLength();
331 for(;pIter
!= pEnd
;++pIter
)
333 if( *pIter
!= cppu::UnoType
<XRename
>::get())
335 aOwnTypes
.push_back(*pIter
);
338 return Sequence
< Type
>(aOwnTypes
.data(), aOwnTypes
.size());
340 return OTableHelper::getTypes();
344 void SAL_CALL
OHSQLTable::rename( const OUString
& newName
)
346 ::osl::MutexGuard
aGuard(m_aMutex
);
349 ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper
.bDisposed
357 OUString sSql
= "ALTER ";
358 if ( m_Type
== "VIEW" )
363 OUString sCatalog
,sSchema
,sTable
;
364 ::dbtools::qualifiedNameComponents(getMetaData(),newName
,sCatalog
,sSchema
,sTable
,::dbtools::EComposeRule::InDataManipulation
);
367 ::dbtools::composeTableName( getMetaData(), m_CatalogName
, m_SchemaName
, m_Name
, true, ::dbtools::EComposeRule::InDataManipulation
)
369 + ::dbtools::composeTableName( getMetaData(), sCatalog
, sSchema
, sTable
, true, ::dbtools::EComposeRule::InDataManipulation
);
371 executeStatement(sSql
);
373 ::connectivity::OTable_TYPEDEF::rename(newName
);
376 ::dbtools::qualifiedNameComponents(getMetaData(),newName
,m_CatalogName
,m_SchemaName
,m_Name
,::dbtools::EComposeRule::InTableDefinitions
);
380 Any SAL_CALL
OHSQLTable::queryInterface( const Type
& rType
)
382 if( m_Type
== "VIEW" && rType
== cppu::UnoType
<XRename
>::get())
385 return OTableHelper::queryInterface(rType
);
389 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */