build fix
[LibreOffice.git] / connectivity / source / drivers / hsqldb / HTable.cxx
blob8a2aea665be89a851616eeb97680f3b5d15c3331
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <string.h>
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 |
64 Privilege::ALTER |
65 Privilege::CREATE |
66 Privilege::READ |
67 Privilege::DELETE |
68 Privilege::UPDATE |
69 Privilege::INSERT |
70 Privilege::SELECT;
71 construct();
74 OHSQLTable::OHSQLTable( sdbcx::OCollection* _pTables,
75 const Reference< XConnection >& _xConnection,
76 const OUString& Name,
77 const OUString& Type,
78 const OUString& Description ,
79 const OUString& SchemaName,
80 const OUString& CatalogName,
81 sal_Int32 _nPrivileges
82 ) : OTableHelper( _pTables,
83 _xConnection,
84 true,
85 Name,
86 Type,
87 Description,
88 SchemaName,
89 CatalogName)
90 , m_nPrivileges(_nPrivileges)
92 construct();
95 void OHSQLTable::construct()
97 OTableHelper::construct();
98 if ( !isNew() )
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);
116 return pColumns;
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;
132 if (! pId)
134 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
135 if (! pId)
137 static ::cppu::OImplementationId aId;
138 pId = &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);
153 // XAlterTable
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);
157 checkDisposed(
158 #ifdef __GNUC__
159 ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper.bDisposed
160 #else
161 rBHelper.bDisposed
162 #endif
165 if ( !m_pColumns || !m_pColumns->hasByName(colName) )
166 throw NoSuchElementException(colName,*this);
169 if ( !isNew() )
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();
180 // type/typename
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() +
210 " ALTER COLUMN " +
211 ::dbtools::quoteName(sQuote,colName) +
212 " RENAME TO " +
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();
250 else
252 if(m_pColumns)
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();
277 #else
278 (void)_rColName;
279 #endif
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() +
294 " ALTER COLUMN " +
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() +
305 " ALTER COLUMN " +
306 ::dbtools::quoteName(sQuote,_rColName) +
307 " DROP DEFAULT";
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;
319 return sSql;
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( );
329 if ( xStmt.is() )
331 try { xStmt->execute(sSQL); }
332 catch( const Exception& )
334 ::comphelper::disposeComponent(xStmt);
335 throw;
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();
362 // XRename
363 void SAL_CALL OHSQLTable::rename( const OUString& newName ) throw(SQLException, ElementExistException, RuntimeException, std::exception)
365 ::osl::MutexGuard aGuard(m_aMutex);
366 checkDisposed(
367 #ifdef __GNUC__
368 ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper.bDisposed
369 #else
370 rBHelper.bDisposed
371 #endif
374 if(!isNew())
376 OUString sSql = "ALTER ";
377 if ( m_Type == "VIEW" )
378 sSql += " VIEW ";
379 else
380 sSql += " TABLE ";
382 OUString sCatalog,sSchema,sTable;
383 ::dbtools::qualifiedNameComponents(getMetaData(),newName,sCatalog,sSchema,sTable,::dbtools::EComposeRule::InDataManipulation);
385 sSql +=
386 ::dbtools::composeTableName( getMetaData(), m_CatalogName, m_SchemaName, m_Name, true, ::dbtools::EComposeRule::InDataManipulation )
387 + " RENAME TO "
388 + ::dbtools::composeTableName( getMetaData(), sCatalog, sSchema, sTable, true, ::dbtools::EComposeRule::InDataManipulation );
390 executeStatement(sSql);
392 ::connectivity::OTable_TYPEDEF::rename(newName);
394 else
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())
402 return Any();
404 return OTableHelper::queryInterface(rType);
408 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */