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 <com/sun/star/beans/PropertyAttribute.hpp>
22 #include <com/sun/star/sdbcx/Privilege.hpp>
23 #include <comphelper/property.hxx>
24 #include <comphelper/servicehelper.hxx>
25 #include <comphelper/types.hxx>
26 #include <connectivity/dbtools.hxx>
27 #include <connectivity/TKeys.hxx>
28 #include <connectivity/TIndexes.hxx>
29 #include <hsqldb/HColumns.hxx>
30 #include <TConnection.hxx>
32 #include <comphelper/diagnose_ex.hxx>
35 using namespace ::comphelper
;
36 using namespace connectivity::hsqldb
;
37 using namespace connectivity::sdbcx
;
38 using namespace connectivity
;
39 using namespace ::com::sun::star::uno
;
40 using namespace ::com::sun::star::beans
;
41 using namespace ::com::sun::star::sdbcx
;
42 using namespace ::com::sun::star::sdbc
;
43 using namespace ::com::sun::star::container
;
44 using namespace ::com::sun::star::lang
;
46 OHSQLTable::OHSQLTable( sdbcx::OCollection
* _pTables
,
47 const Reference
< XConnection
>& _xConnection
)
48 :OTableHelper(_pTables
,_xConnection
,true)
50 // we create a new table here, so we should have all the rights or ;-)
51 m_nPrivileges
= Privilege::DROP
|
52 Privilege::REFERENCE
|
63 OHSQLTable::OHSQLTable( sdbcx::OCollection
* _pTables
,
64 const Reference
< XConnection
>& _xConnection
,
67 const OUString
& Description
,
68 const OUString
& SchemaName
,
69 const OUString
& CatalogName
,
70 sal_Int32 _nPrivileges
71 ) : OTableHelper( _pTables
,
79 , m_nPrivileges(_nPrivileges
)
84 void OHSQLTable::construct()
86 OTableHelper::construct();
88 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRIVILEGES
), PROPERTY_ID_PRIVILEGES
,PropertyAttribute::READONLY
,&m_nPrivileges
, cppu::UnoType
<decltype(m_nPrivileges
)>::get());
91 ::cppu::IPropertyArrayHelper
* OHSQLTable::createArrayHelper( sal_Int32
/*_nId*/ ) const
93 return doCreateArrayHelper();
96 ::cppu::IPropertyArrayHelper
& OHSQLTable::getInfoHelper()
98 return *static_cast<OHSQLTable_PROP
*>(this)->getArrayHelper(isNew() ? 1 : 0);
101 sdbcx::OCollection
* OHSQLTable::createColumns(const ::std::vector
< OUString
>& _rNames
)
103 OHSQLColumns
* pColumns
= new OHSQLColumns(*this,m_aMutex
,_rNames
);
104 pColumns
->setParent(this);
108 sdbcx::OCollection
* OHSQLTable::createKeys(const ::std::vector
< OUString
>& _rNames
)
110 return new OKeysHelper(this,m_aMutex
,_rNames
);
113 sdbcx::OCollection
* OHSQLTable::createIndexes(const ::std::vector
< OUString
>& _rNames
)
115 return new OIndexesHelper(this,m_aMutex
,_rNames
);
120 void SAL_CALL
OHSQLTable::alterColumnByName( const OUString
& colName
, const Reference
< XPropertySet
>& descriptor
)
122 ::osl::MutexGuard
aGuard(m_aMutex
);
125 ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper
.bDisposed
131 if ( !m_xColumns
|| !m_xColumns
->hasByName(colName
) )
132 throw NoSuchElementException(colName
,*this);
137 // first we have to check what should be altered
138 Reference
<XPropertySet
> xProp
;
139 m_xColumns
->getByName(colName
) >>= xProp
;
140 // first check the types
141 sal_Int32 nOldType
= 0,nNewType
= 0,nOldPrec
= 0,nNewPrec
= 0,nOldScale
= 0,nNewScale
= 0;
142 OUString sOldTypeName
, sNewTypeName
;
144 ::dbtools::OPropertyMap
& rProp
= OMetaConnection::getPropMap();
147 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPE
)) >>= nOldType
;
148 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPE
)) >>= nNewType
;
149 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPENAME
)) >>= sOldTypeName
;
150 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_TYPENAME
))>>= sNewTypeName
;
152 // and precision and scale
153 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_PRECISION
)) >>= nOldPrec
;
154 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_PRECISION
))>>= nNewPrec
;
155 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_SCALE
)) >>= nOldScale
;
156 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_SCALE
)) >>= nNewScale
;
158 // second: check the "is nullable" value
159 sal_Int32 nOldNullable
= 0,nNewNullable
= 0;
160 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_ISNULLABLE
)) >>= nOldNullable
;
161 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_ISNULLABLE
)) >>= nNewNullable
;
163 // check also the auto_increment
164 bool bOldAutoIncrement
= false,bAutoIncrement
= false;
165 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT
)) >>= bOldAutoIncrement
;
166 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_ISAUTOINCREMENT
)) >>= bAutoIncrement
;
168 // now we should look if the name of the column changed
169 OUString sNewColumnName
;
170 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_NAME
)) >>= sNewColumnName
;
171 if ( sNewColumnName
!= colName
)
173 const OUString sQuote
= getMetaData()->getIdentifierQuoteString( );
175 OUString sSql
= getAlterTableColumnPart() +
177 ::dbtools::quoteName(sQuote
,colName
) +
179 ::dbtools::quoteName(sQuote
,sNewColumnName
);
181 executeStatement(sSql
);
184 if ( nOldType
!= nNewType
185 || sOldTypeName
!= sNewTypeName
186 || nOldPrec
!= nNewPrec
187 || nOldScale
!= nNewScale
188 || nNewNullable
!= nOldNullable
189 || bOldAutoIncrement
!= bAutoIncrement
)
191 // special handling because they change the type names to distinguish
192 // if a column should be an auto_increment one
193 if ( bOldAutoIncrement
!= bAutoIncrement
)
195 /// TODO: insert special handling for auto increment "IDENTITY" and primary key
197 alterColumnType(nNewType
,sNewColumnName
,descriptor
);
200 // third: check the default values
201 OUString sNewDefault
,sOldDefault
;
202 xProp
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_DEFAULTVALUE
)) >>= sOldDefault
;
203 descriptor
->getPropertyValue(rProp
.getNameByIndex(PROPERTY_ID_DEFAULTVALUE
)) >>= sNewDefault
;
205 if(!sOldDefault
.isEmpty())
207 dropDefaultValue(colName
);
208 if(!sNewDefault
.isEmpty() && sOldDefault
!= sNewDefault
)
209 alterDefaultValue(sNewDefault
,sNewColumnName
);
211 else if(sOldDefault
.isEmpty() && !sNewDefault
.isEmpty())
212 alterDefaultValue(sNewDefault
,sNewColumnName
);
214 m_xColumns
->refresh();
220 m_xColumns
->dropByName(colName
);
221 m_xColumns
->appendByDescriptor(descriptor
);
227 void OHSQLTable::alterColumnType(sal_Int32 nNewType
,const OUString
& _rColName
, const Reference
<XPropertySet
>& _xDescriptor
)
229 OUString sSql
= getAlterTableColumnPart() + " ALTER COLUMN ";
230 #if OSL_DEBUG_LEVEL > 0
233 OUString sDescriptorName
;
234 OSL_ENSURE( _xDescriptor
.is()
235 && ( _xDescriptor
->getPropertyValue( OMetaConnection::getPropMap().getNameByIndex( PROPERTY_ID_NAME
) ) >>= sDescriptorName
)
236 && ( sDescriptorName
== _rColName
),
237 "OHSQLTable::alterColumnType: unexpected column name!" );
239 catch( const Exception
& )
241 DBG_UNHANDLED_EXCEPTION("connectivity.hsqldb");
247 rtl::Reference
<OHSQLColumn
> pColumn
= new OHSQLColumn
;
248 ::comphelper::copyProperties(_xDescriptor
,pColumn
);
249 pColumn
->setPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE
),Any(nNewType
));
251 sSql
+= ::dbtools::createStandardColumnPart(pColumn
,getConnection());
252 executeStatement(sSql
);
255 void OHSQLTable::alterDefaultValue(std::u16string_view _sNewDefault
,const OUString
& _rColName
)
257 const OUString sQuote
= getMetaData()->getIdentifierQuoteString( );
258 OUString sSql
= getAlterTableColumnPart() +
260 ::dbtools::quoteName(sQuote
,_rColName
) +
261 " SET DEFAULT '" + _sNewDefault
+ "'";
263 executeStatement(sSql
);
266 void OHSQLTable::dropDefaultValue(const OUString
& _rColName
)
268 const OUString sQuote
= getMetaData()->getIdentifierQuoteString( );
269 OUString sSql
= getAlterTableColumnPart() +
271 ::dbtools::quoteName(sQuote
,_rColName
) +
274 executeStatement(sSql
);
277 OUString
OHSQLTable::getAlterTableColumnPart() const
279 OUString
sSql( "ALTER TABLE " );
281 OUString
sComposedName( ::dbtools::composeTableName( getMetaData(), m_CatalogName
, m_SchemaName
, m_Name
, true, ::dbtools::EComposeRule::InTableDefinitions
) );
282 sSql
+= sComposedName
;
287 void OHSQLTable::executeStatement(const OUString
& _rStatement
)
289 OUString sSQL
= _rStatement
;
290 if(sSQL
.endsWith(","))
291 sSQL
= sSQL
.replaceAt(sSQL
.getLength()-1, 1, u
")");
293 Reference
< XStatement
> xStmt
= getConnection()->createStatement( );
296 try { xStmt
->execute(sSQL
); }
297 catch( const Exception
& )
299 ::comphelper::disposeComponent(xStmt
);
302 ::comphelper::disposeComponent(xStmt
);
306 Sequence
< Type
> SAL_CALL
OHSQLTable::getTypes( )
308 if ( m_Type
== "VIEW" )
310 Sequence
< Type
> aTypes
= OTableHelper::getTypes();
311 std::vector
<Type
> aOwnTypes
;
312 aOwnTypes
.reserve(aTypes
.getLength());
313 const Type
* pIter
= aTypes
.getConstArray();
314 const Type
* pEnd
= pIter
+ aTypes
.getLength();
315 for(;pIter
!= pEnd
;++pIter
)
317 if( *pIter
!= cppu::UnoType
<XRename
>::get())
319 aOwnTypes
.push_back(*pIter
);
322 return Sequence
< Type
>(aOwnTypes
.data(), aOwnTypes
.size());
324 return OTableHelper::getTypes();
328 void SAL_CALL
OHSQLTable::rename( const OUString
& newName
)
330 ::osl::MutexGuard
aGuard(m_aMutex
);
333 ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper
.bDisposed
341 OUString sSql
= "ALTER ";
342 if ( m_Type
== "VIEW" )
347 OUString sCatalog
,sSchema
,sTable
;
348 ::dbtools::qualifiedNameComponents(getMetaData(),newName
,sCatalog
,sSchema
,sTable
,::dbtools::EComposeRule::InDataManipulation
);
351 ::dbtools::composeTableName( getMetaData(), m_CatalogName
, m_SchemaName
, m_Name
, true, ::dbtools::EComposeRule::InDataManipulation
)
353 + ::dbtools::composeTableName( getMetaData(), sCatalog
, sSchema
, sTable
, true, ::dbtools::EComposeRule::InDataManipulation
);
355 executeStatement(sSql
);
357 ::connectivity::OTable_TYPEDEF::rename(newName
);
360 ::dbtools::qualifiedNameComponents(getMetaData(),newName
,m_CatalogName
,m_SchemaName
,m_Name
,::dbtools::EComposeRule::InTableDefinitions
);
364 Any SAL_CALL
OHSQLTable::queryInterface( const Type
& rType
)
366 if( m_Type
== "VIEW" && rType
== cppu::UnoType
<XRename
>::get())
369 return OTableHelper::queryInterface(rType
);
373 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */