Version 4.0.0.1, tag libreoffice-4.0.0.1
[LibreOffice.git] / dbaccess / source / core / api / tablecontainer.cxx
blob2a334599f3f1c10ccdbb6a8899956192abba9bff
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 .
21 #include "tablecontainer.hxx"
22 #include "dbastrings.hrc"
23 #include "table.hxx"
24 #include <comphelper/property.hxx>
25 #include <comphelper/processfactory.hxx>
26 #include <tools/debug.hxx>
27 #include <comphelper/enumhelper.hxx>
28 #include "core_resource.hxx"
29 #include "core_resource.hrc"
30 #include <com/sun/star/sdb/CommandType.hpp>
31 #include <com/sun/star/beans/XPropertySet.hpp>
32 #include <com/sun/star/beans/PropertyState.hpp>
33 #include <com/sun/star/beans/XPropertyState.hpp>
34 #include <com/sun/star/sdbc/XConnection.hpp>
35 #include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
36 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
37 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
38 #include <com/sun/star/sdbc/KeyRule.hpp>
39 #include <com/sun/star/sdbcx/KeyType.hpp>
40 #include <com/sun/star/sdbc/ColumnValue.hpp>
41 #include <com/sun/star/sdbc/XRow.hpp>
42 #include <comphelper/types.hxx>
43 #include <connectivity/dbtools.hxx>
44 #include <comphelper/extract.hxx>
45 #include <connectivity/dbexception.hxx>
46 #include "TableDeco.hxx"
47 #include "sdbcoretools.hxx"
48 #include "ContainerMediator.hxx"
49 #include "definitioncolumn.hxx"
50 #include "objectnameapproval.hxx"
51 #include <tools/string.hxx>
52 #include <rtl/logfile.hxx>
53 #include <tools/diagnose_ex.h>
55 using namespace dbaccess;
56 using namespace dbtools;
57 using namespace ::com::sun::star::uno;
58 using namespace ::com::sun::star::lang;
59 using namespace ::com::sun::star::beans;
60 using namespace ::com::sun::star::sdbc;
61 using namespace ::com::sun::star::sdb;
62 using namespace ::com::sun::star::sdbcx;
63 using namespace ::com::sun::star::container;
64 using namespace ::com::sun::star::util;
65 using namespace ::osl;
66 using namespace ::comphelper;
67 using namespace ::cppu;
68 using namespace ::connectivity::sdbcx;
70 namespace
72 sal_Bool lcl_isPropertySetDefaulted(const Sequence< ::rtl::OUString>& _aNames,const Reference<XPropertySet>& _xProp)
74 Reference<XPropertyState> xState(_xProp,UNO_QUERY);
75 if ( xState.is() )
77 const ::rtl::OUString* pIter = _aNames.getConstArray();
78 const ::rtl::OUString* pEnd = pIter + _aNames.getLength();
79 for(;pIter != pEnd;++pIter)
81 try
83 PropertyState aState = xState->getPropertyState(*pIter);
84 if ( aState != PropertyState_DEFAULT_VALUE )
85 break;
87 catch(const Exception&)
89 OSL_FAIL( "lcl_isPropertySetDefaulted: Exception caught!" );
92 return ( pIter == pEnd );
94 return sal_False;
97 //==========================================================================
98 //= OTableContainer
99 //==========================================================================
100 DBG_NAME(OTableContainer)
102 OTableContainer::OTableContainer(::cppu::OWeakObject& _rParent,
103 ::osl::Mutex& _rMutex,
104 const Reference< XConnection >& _xCon,
105 sal_Bool _bCase,
106 const Reference< XNameContainer >& _xTableDefinitions,
107 IRefreshListener* _pRefreshListener,
108 ::dbtools::IWarningsContainer* _pWarningsContainer
109 ,oslInterlockedCount& _nInAppend)
110 :OFilteredContainer(_rParent,_rMutex,_xCon,_bCase,_pRefreshListener,_pWarningsContainer,_nInAppend)
111 ,m_xTableDefinitions(_xTableDefinitions)
112 ,m_pTableMediator( NULL )
113 ,m_bInDrop(sal_False)
115 DBG_CTOR(OTableContainer, NULL);
118 OTableContainer::~OTableContainer()
120 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::OTableContainer" );
121 DBG_DTOR(OTableContainer, NULL);
124 void OTableContainer::removeMasterContainerListener()
126 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::removeMasterContainerListener" );
129 Reference<XContainer> xCont( m_xMasterContainer, UNO_QUERY_THROW );
130 xCont->removeContainerListener( this );
132 catch( const Exception& )
134 DBG_UNHANDLED_EXCEPTION();
138 ::rtl::OUString OTableContainer::getTableTypeRestriction() const
140 // no restriction at all (other than the ones provided externally)
141 return ::rtl::OUString();
144 // XServiceInfo
145 IMPLEMENT_SERVICE_INFO2(OTableContainer, "com.sun.star.sdb.dbaccess.OTableContainer", SERVICE_SDBCX_CONTAINER.ascii, SERVICE_SDBCX_TABLES.ascii)
147 namespace
149 void lcl_createDefintionObject(const ::rtl::OUString& _rName
150 ,const Reference< XNameContainer >& _xTableDefinitions
151 ,Reference<XPropertySet>& _xTableDefinition
152 ,Reference<XNameAccess>& _xColumnDefinitions
153 ,sal_Bool _bModified)
155 if ( _xTableDefinitions.is() )
157 if ( _xTableDefinitions->hasByName(_rName) )
158 _xTableDefinition.set(_xTableDefinitions->getByName(_rName),UNO_QUERY);
159 else
161 Sequence< Any > aArguments(1);
162 PropertyValue aValue;
163 // set as folder
164 aValue.Name = PROPERTY_NAME;
165 aValue.Value <<= _rName;
166 aArguments[0] <<= aValue;
167 _xTableDefinition.set(::comphelper::getProcessServiceFactory()->createInstanceWithArguments(SERVICE_SDB_TABLEDEFINITION,aArguments),UNO_QUERY);
168 _xTableDefinitions->insertByName(_rName,makeAny(_xTableDefinition));
169 ::dbaccess::notifyDataSourceModified(_xTableDefinitions,_bModified);
171 Reference<XColumnsSupplier> xColumnsSupplier(_xTableDefinition,UNO_QUERY);
172 if ( xColumnsSupplier.is() )
173 _xColumnDefinitions = xColumnsSupplier->getColumns();
179 connectivity::sdbcx::ObjectType OTableContainer::createObject(const ::rtl::OUString& _rName)
181 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::createObject" );
182 Reference<XColumnsSupplier > xSup;
183 if(m_xMasterContainer.is() && m_xMasterContainer->hasByName(_rName))
184 xSup.set(m_xMasterContainer->getByName(_rName),UNO_QUERY);
186 connectivity::sdbcx::ObjectType xRet;
187 if ( m_xMetaData.is() )
189 Reference<XPropertySet> xTableDefinition;
190 Reference<XNameAccess> xColumnDefinitions;
191 lcl_createDefintionObject(_rName,m_xTableDefinitions,xTableDefinition,xColumnDefinitions,sal_False);
193 if ( xSup.is() )
195 ODBTableDecorator* pTable = new ODBTableDecorator( m_xConnection, xSup, ::dbtools::getNumberFormats( m_xConnection ) ,xColumnDefinitions);
196 xRet = pTable;
197 pTable->construct();
199 else
201 ::rtl::OUString sCatalog,sSchema,sTable;
202 ::dbtools::qualifiedNameComponents(m_xMetaData,
203 _rName,
204 sCatalog,
205 sSchema,
206 sTable,
207 ::dbtools::eInDataManipulation);
208 Any aCatalog;
209 if(!sCatalog.isEmpty())
210 aCatalog <<= sCatalog;
211 ::rtl::OUString sType,sDescription;
212 Sequence< ::rtl::OUString> aTypeFilter;
213 getAllTableTypeFilter( aTypeFilter );
215 Reference< XResultSet > xRes = m_xMetaData.is() ? m_xMetaData->getTables(aCatalog,sSchema,sTable,aTypeFilter) : Reference< XResultSet >();
216 if(xRes.is() && xRes->next())
218 Reference< XRow > xRow(xRes,UNO_QUERY);
219 if(xRow.is())
221 sType = xRow->getString(4);
222 sDescription = xRow->getString(5);
225 ::comphelper::disposeComponent(xRes);
226 ODBTable* pTable = new ODBTable(this
227 ,m_xConnection
228 ,sCatalog
229 ,sSchema
230 ,sTable
231 ,sType
232 ,sDescription
233 ,xColumnDefinitions);
234 xRet = pTable;
235 pTable->construct();
237 Reference<XPropertySet> xDest(xRet,UNO_QUERY);
238 if ( xTableDefinition.is() )
239 ::comphelper::copyProperties(xTableDefinition,xDest);
241 if ( !m_pTableMediator.is() )
242 m_pTableMediator = new OContainerMediator(
243 this, m_xTableDefinitions.get(), m_xConnection );
244 if ( m_pTableMediator.is() )
245 m_pTableMediator->notifyElementCreated(_rName,xDest);
248 return xRet;
251 Reference< XPropertySet > OTableContainer::createDescriptor()
253 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::createDescriptor" );
254 Reference< XPropertySet > xRet;
256 // first we have to look if the master tables support this
257 // and if so then create a table object as well with the master tables
258 Reference<XColumnsSupplier > xMasterColumnsSup;
259 Reference<XDataDescriptorFactory> xDataFactory(m_xMasterContainer,UNO_QUERY);
260 if ( xDataFactory.is() && m_xMetaData.is() )
262 xMasterColumnsSup = Reference< XColumnsSupplier >( xDataFactory->createDataDescriptor(), UNO_QUERY );
263 ODBTableDecorator* pTable = new ODBTableDecorator( m_xConnection, xMasterColumnsSup, ::dbtools::getNumberFormats( m_xConnection ) ,NULL);
264 xRet = pTable;
265 pTable->construct();
267 else
269 ODBTable* pTable = new ODBTable(this, m_xConnection);
270 xRet = pTable;
271 pTable->construct();
273 return xRet;
276 // XAppend
277 ObjectType OTableContainer::appendObject( const ::rtl::OUString& _rForName, const Reference< XPropertySet >& descriptor )
279 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::appendObject" );
280 // append the new table with a create stmt
281 ::rtl::OUString aName = getString(descriptor->getPropertyValue(PROPERTY_NAME));
282 if(m_xMasterContainer.is() && m_xMasterContainer->hasByName(aName))
284 String sMessage(DBACORE_RESSTRING(RID_STR_TABLE_IS_FILTERED));
285 sMessage.SearchAndReplaceAscii("$name$", aName);
286 throw SQLException(sMessage,static_cast<XTypeProvider*>(static_cast<OFilteredContainer*>(this)),SQLSTATE_GENERAL,1000,Any());
289 Reference< XConnection > xConnection( m_xConnection.get(), UNO_QUERY );
290 PContainerApprove pApprove( new ObjectNameApproval( xConnection, ObjectNameApproval::TypeTable ) );
291 pApprove->approveElement( aName, descriptor );
295 EnsureReset aReset(m_nInAppend);
296 Reference<XAppend> xAppend(m_xMasterContainer,UNO_QUERY);
297 if(xAppend.is())
299 xAppend->appendByDescriptor(descriptor);
301 else
303 ::rtl::OUString aSql = ::dbtools::createSqlCreateTableStatement(descriptor,m_xConnection);
305 Reference<XConnection> xCon = m_xConnection;
306 OSL_ENSURE(xCon.is(),"Connection is null!");
307 if ( xCon.is() )
309 Reference< XStatement > xStmt = xCon->createStatement( );
310 if ( xStmt.is() )
311 xStmt->execute(aSql);
312 ::comphelper::disposeComponent(xStmt);
316 catch(const Exception&)
318 throw;
321 Reference<XPropertySet> xTableDefinition;
322 Reference<XNameAccess> xColumnDefinitions;
323 lcl_createDefintionObject(getNameForObject(descriptor),m_xTableDefinitions,xTableDefinition,xColumnDefinitions,sal_False);
324 Reference<XColumnsSupplier> xSup(descriptor,UNO_QUERY);
325 Reference<XDataDescriptorFactory> xFac(xColumnDefinitions,UNO_QUERY);
326 Reference<XAppend> xAppend(xColumnDefinitions,UNO_QUERY);
327 sal_Bool bModified = sal_False;
328 if ( xSup.is() && xColumnDefinitions.is() && xFac.is() && xAppend.is() )
330 Reference<XNameAccess> xNames = xSup->getColumns();
331 if ( xNames.is() )
333 Reference<XPropertySet> xProp = xFac->createDataDescriptor();
334 Sequence< ::rtl::OUString> aSeq = xNames->getElementNames();
335 const ::rtl::OUString* pIter = aSeq.getConstArray();
336 const ::rtl::OUString* pEnd = pIter + aSeq.getLength();
337 for(;pIter != pEnd;++pIter)
339 if ( !xColumnDefinitions->hasByName(*pIter) )
341 Reference<XPropertySet> xColumn(xNames->getByName(*pIter),UNO_QUERY);
342 if ( !OColumnSettings::hasDefaultSettings( xColumn ) )
344 ::comphelper::copyProperties( xColumn, xProp );
345 xAppend->appendByDescriptor( xProp );
346 bModified = sal_True;
352 const static ::rtl::OUString s_pTableProps[] = { ::rtl::OUString(PROPERTY_FILTER), ::rtl::OUString(PROPERTY_ORDER)
353 , ::rtl::OUString(PROPERTY_APPLYFILTER), ::rtl::OUString(PROPERTY_FONT)
354 , ::rtl::OUString(PROPERTY_ROW_HEIGHT), ::rtl::OUString(PROPERTY_TEXTCOLOR)
355 , ::rtl::OUString(PROPERTY_TEXTLINECOLOR), ::rtl::OUString(PROPERTY_TEXTEMPHASIS)
356 , ::rtl::OUString(PROPERTY_TEXTRELIEF) };
357 Sequence< ::rtl::OUString> aNames(s_pTableProps,sizeof(s_pTableProps)/sizeof(s_pTableProps[0]));
358 if ( bModified || !lcl_isPropertySetDefaulted(aNames,xTableDefinition) )
359 ::dbaccess::notifyDataSourceModified(m_xTableDefinitions,sal_True);
361 return createObject( _rForName );
364 // XDrop
365 void OTableContainer::dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName)
367 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::dropObject" );
368 m_bInDrop = sal_True;
371 Reference< XDrop > xDrop(m_xMasterContainer,UNO_QUERY);
372 if(xDrop.is())
373 xDrop->dropByName(_sElementName);
374 else
376 ::rtl::OUString sCatalog,sSchema,sTable,sComposedName;
378 sal_Bool bIsView = sal_False;
379 Reference<XPropertySet> xTable(getObject(_nPos),UNO_QUERY);
380 if ( xTable.is() && m_xMetaData.is() )
382 if( m_xMetaData.is() && m_xMetaData->supportsCatalogsInTableDefinitions() )
383 xTable->getPropertyValue(PROPERTY_CATALOGNAME) >>= sCatalog;
384 if( m_xMetaData.is() && m_xMetaData->supportsSchemasInTableDefinitions() )
385 xTable->getPropertyValue(PROPERTY_SCHEMANAME) >>= sSchema;
386 xTable->getPropertyValue(PROPERTY_NAME) >>= sTable;
388 sComposedName = ::dbtools::composeTableName( m_xMetaData, sCatalog, sSchema, sTable, sal_True, ::dbtools::eInTableDefinitions );
390 ::rtl::OUString sType;
391 xTable->getPropertyValue(PROPERTY_TYPE) >>= sType;
392 bIsView = sType.equalsIgnoreAsciiCase(::rtl::OUString("VIEW"));
395 if(sComposedName.isEmpty())
396 ::dbtools::throwFunctionSequenceException(static_cast<XTypeProvider*>(static_cast<OFilteredContainer*>(this)));
398 ::rtl::OUString aSql("DROP ");
400 if ( bIsView ) // here we have a view
401 aSql += ::rtl::OUString("VIEW ");
402 else
403 aSql += ::rtl::OUString("TABLE ");
404 aSql += sComposedName;
405 Reference<XConnection> xCon = m_xConnection;
406 OSL_ENSURE(xCon.is(),"Connection is null!");
407 if ( xCon.is() )
409 Reference< XStatement > xStmt = xCon->createStatement( );
410 if(xStmt.is())
411 xStmt->execute(aSql);
412 ::comphelper::disposeComponent(xStmt);
416 if ( m_xTableDefinitions.is() && m_xTableDefinitions->hasByName(_sElementName) )
418 m_xTableDefinitions->removeByName(_sElementName);
421 catch(const Exception&)
423 m_bInDrop = sal_False;
424 throw;
426 m_bInDrop = sal_False;
429 void SAL_CALL OTableContainer::elementInserted( const ContainerEvent& Event ) throw (RuntimeException)
431 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::elementInserted" );
432 ::osl::MutexGuard aGuard(m_rMutex);
433 ::rtl::OUString sName;
434 Event.Accessor >>= sName;
435 if ( !m_nInAppend && !hasByName(sName) )
437 if(!m_xMasterContainer.is() || m_xMasterContainer->hasByName(sName))
439 ObjectType xName = createObject(sName);
440 insertElement(sName,xName);
441 // and notify our listeners
442 ContainerEvent aEvent(static_cast<XContainer*>(this), makeAny(sName), makeAny(xName), Any());
443 m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent );
448 void SAL_CALL OTableContainer::elementRemoved( const ContainerEvent& /*Event*/ ) throw (RuntimeException)
450 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::elementRemoved" );
453 void SAL_CALL OTableContainer::elementReplaced( const ContainerEvent& Event ) throw (RuntimeException)
455 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::elementReplaced" );
456 // create a new config entry
458 ::rtl::OUString sOldComposedName,sNewComposedName;
459 Event.ReplacedElement >>= sOldComposedName;
460 Event.Accessor >>= sNewComposedName;
462 renameObject(sOldComposedName,sNewComposedName);
466 void SAL_CALL OTableContainer::disposing()
468 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::disposing" );
469 OFilteredContainer::disposing();
470 // say goodbye to our listeners
471 m_xTableDefinitions = NULL;
472 m_pTableMediator = NULL;
475 void SAL_CALL OTableContainer::disposing( const ::com::sun::star::lang::EventObject& /*Source*/ ) throw (::com::sun::star::uno::RuntimeException)
477 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "api", "Ocke.Janssen@sun.com", "OTableContainer::disposing" );
480 void OTableContainer::addMasterContainerListener()
484 Reference< XContainer > xCont( m_xMasterContainer, UNO_QUERY_THROW );
485 xCont->addContainerListener( this );
487 catch( const Exception& )
489 DBG_UNHANDLED_EXCEPTION();
492 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */