Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / connectivity / source / drivers / hsqldb / HTable.cxx
blob63fe36a34a347cdcd6a435d8bc970f1e23bd557b
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 <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 |
53 Privilege::ALTER |
54 Privilege::CREATE |
55 Privilege::READ |
56 Privilege::DELETE |
57 Privilege::UPDATE |
58 Privilege::INSERT |
59 Privilege::SELECT;
60 construct();
63 OHSQLTable::OHSQLTable( sdbcx::OCollection* _pTables,
64 const Reference< XConnection >& _xConnection,
65 const OUString& Name,
66 const OUString& Type,
67 const OUString& Description ,
68 const OUString& SchemaName,
69 const OUString& CatalogName,
70 sal_Int32 _nPrivileges
71 ) : OTableHelper( _pTables,
72 _xConnection,
73 true,
74 Name,
75 Type,
76 Description,
77 SchemaName,
78 CatalogName)
79 , m_nPrivileges(_nPrivileges)
81 construct();
84 void OHSQLTable::construct()
86 OTableHelper::construct();
87 if ( !isNew() )
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);
105 return pColumns;
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);
119 // XAlterTable
120 void SAL_CALL OHSQLTable::alterColumnByName( const OUString& colName, const Reference< XPropertySet >& descriptor )
122 ::osl::MutexGuard aGuard(m_aMutex);
123 checkDisposed(
124 #ifdef __GNUC__
125 ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper.bDisposed
126 #else
127 rBHelper.bDisposed
128 #endif
131 if ( !m_xColumns || !m_xColumns->hasByName(colName) )
132 throw NoSuchElementException(colName,*this);
135 if ( !isNew() )
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();
146 // type/typename
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() +
176 " ALTER COLUMN " +
177 ::dbtools::quoteName(sQuote,colName) +
178 " RENAME TO " +
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();
216 else
218 if(m_xColumns)
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");
243 #else
244 (void)_rColName;
245 #endif
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() +
259 " ALTER COLUMN " +
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() +
270 " ALTER COLUMN " +
271 ::dbtools::quoteName(sQuote,_rColName) +
272 " DROP DEFAULT";
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;
284 return sSql;
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( );
294 if ( xStmt.is() )
296 try { xStmt->execute(sSQL); }
297 catch( const Exception& )
299 ::comphelper::disposeComponent(xStmt);
300 throw;
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();
327 // XRename
328 void SAL_CALL OHSQLTable::rename( const OUString& newName )
330 ::osl::MutexGuard aGuard(m_aMutex);
331 checkDisposed(
332 #ifdef __GNUC__
333 ::connectivity::sdbcx::OTableDescriptor_BASE::rBHelper.bDisposed
334 #else
335 rBHelper.bDisposed
336 #endif
339 if(!isNew())
341 OUString sSql = "ALTER ";
342 if ( m_Type == "VIEW" )
343 sSql += " VIEW ";
344 else
345 sSql += " TABLE ";
347 OUString sCatalog,sSchema,sTable;
348 ::dbtools::qualifiedNameComponents(getMetaData(),newName,sCatalog,sSchema,sTable,::dbtools::EComposeRule::InDataManipulation);
350 sSql +=
351 ::dbtools::composeTableName( getMetaData(), m_CatalogName, m_SchemaName, m_Name, true, ::dbtools::EComposeRule::InDataManipulation )
352 + " RENAME TO "
353 + ::dbtools::composeTableName( getMetaData(), sCatalog, sSchema, sTable, true, ::dbtools::EComposeRule::InDataManipulation );
355 executeStatement(sSql);
357 ::connectivity::OTable_TYPEDEF::rename(newName);
359 else
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())
367 return Any();
369 return OTableHelper::queryInterface(rType);
373 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */