xref: /aoo41x/main/dbaccess/source/core/api/column.cxx (revision 96de5490)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_dbaccess.hxx"
26 
27 #include "ContainerMediator.hxx"
28 #include "apitools.hxx"
29 #include "column.hxx"
30 #include "core_resource.hrc"
31 #include "core_resource.hxx"
32 #include "dbastrings.hrc"
33 #include "sdbcoretools.hxx"
34 
35 #include <com/sun/star/lang/DisposedException.hpp>
36 #include <com/sun/star/sdbc/ColumnValue.hpp>
37 #include <com/sun/star/sdbc/DataType.hpp>
38 
39 #include <comphelper/basicio.hxx>
40 #include <comphelper/enumhelper.hxx>
41 #include <comphelper/extract.hxx>
42 #include <comphelper/property.hxx>
43 #include <comphelper/seqstream.hxx>
44 #include <comphelper/sequence.hxx>
45 #include <comphelper/types.hxx>
46 #include <connectivity/TTableHelper.hxx>
47 #include <connectivity/dbexception.hxx>
48 #include <connectivity/dbtools.hxx>
49 #include <cppuhelper/typeprovider.hxx>
50 #include <osl/diagnose.h>
51 #include <tools/debug.hxx>
52 
53 #include <algorithm>
54 
55 using namespace dbaccess;
56 using namespace connectivity;
57 using namespace connectivity;
58 using namespace ::com::sun::star::sdbc;
59 using namespace ::com::sun::star::sdbcx;
60 using namespace ::com::sun::star::beans;
61 using namespace ::com::sun::star::uno;
62 using namespace ::com::sun::star::lang;
63 using namespace ::com::sun::star::awt;
64 using namespace ::com::sun::star::io;
65 using namespace ::com::sun::star::container;
66 using namespace ::com::sun::star::util;
67 using namespace ::osl;
68 using namespace ::comphelper;
69 using namespace ::cppu;
70 
DBG_NAME(OColumn)71 DBG_NAME(OColumn)
72 
73 //============================================================
74 //= OColumn
75 //============================================================
76 //--------------------------------------------------------------------------
77 OColumn::OColumn( const bool _bNameIsReadOnly )
78 	    :OColumnBase( m_aMutex )
79         ,::comphelper::OPropertyContainer( OColumnBase::rBHelper )
80 {
81 	DBG_CTOR(OColumn, NULL);
82 
83     registerProperty( PROPERTY_NAME, PROPERTY_ID_NAME, _bNameIsReadOnly ? PropertyAttribute::READONLY : 0,
84         &m_sName, ::getCppuType( &m_sName ) );
85 }
86 
87 //--------------------------------------------------------------------------
~OColumn()88 OColumn::~OColumn()
89 {
90 	DBG_DTOR(OColumn, NULL);
91 }
92 
93 // com::sun::star::lang::XTypeProvider
94 //--------------------------------------------------------------------------
getTypes()95 Sequence< Type > OColumn::getTypes() throw (RuntimeException)
96 {
97 	return ::comphelper::concatSequences(
98 		OColumnBase::getTypes(),
99 		::comphelper::OPropertyContainer::getTypes()
100 	);
101 }
102 
103 // com::sun::star::uno::XInterface
IMPLEMENT_FORWARD_XINTERFACE2(OColumn,OColumnBase,::comphelper::OPropertyContainer)104 IMPLEMENT_FORWARD_XINTERFACE2( OColumn, OColumnBase, ::comphelper::OPropertyContainer )
105 
106 // ::com::sun::star::lang::XServiceInfo
107 //------------------------------------------------------------------------------
108 rtl::OUString OColumn::getImplementationName(  ) throw(RuntimeException)
109 {
110 	return rtl::OUString::createFromAscii("com.sun.star.sdb.OColumn");
111 }
112 
113 //------------------------------------------------------------------------------
supportsService(const::rtl::OUString & _rServiceName)114 sal_Bool OColumn::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
115 {
116 	return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0;
117 }
118 
119 //------------------------------------------------------------------------------
getSupportedServiceNames()120 Sequence< ::rtl::OUString > OColumn::getSupportedServiceNames(  ) throw (RuntimeException)
121 {
122 	Sequence< ::rtl::OUString > aSNS( 1 );
123 	aSNS[0] = SERVICE_SDBCX_COLUMN;
124 	return aSNS;
125 }
126 
127 // OComponentHelper
128 //------------------------------------------------------------------------------
disposing()129 void OColumn::disposing()
130 {
131 	OPropertyContainer::disposing();
132 }
133 
134 // com::sun::star::beans::XPropertySet
135 //------------------------------------------------------------------------------
getPropertySetInfo()136 Reference< XPropertySetInfo > OColumn::getPropertySetInfo() throw (RuntimeException)
137 {
138 	return createPropertySetInfo( getInfoHelper() ) ;
139 }
140 
141 // -----------------------------------------------------------------------------
getName()142 ::rtl::OUString SAL_CALL OColumn::getName(  ) throw(::com::sun::star::uno::RuntimeException)
143 {
144 	return m_sName;
145 }
146 // -----------------------------------------------------------------------------
setName(const::rtl::OUString & _rName)147 void SAL_CALL OColumn::setName( const ::rtl::OUString& _rName ) throw(::com::sun::star::uno::RuntimeException)
148 {
149 	m_sName = _rName;
150 }
151 
152 // -----------------------------------------------------------------------------
fireValueChange(const::connectivity::ORowSetValue &)153 void OColumn::fireValueChange(const ::connectivity::ORowSetValue& /*_rOldValue*/)
154 {
155     DBG_ERROR( "OColumn::fireValueChange: not implemented!" );
156 }
157 
158 //------------------------------------------------------------------------------
registerProperty(const::rtl::OUString & _rName,sal_Int32 _nHandle,sal_Int32 _nAttributes,void * _pPointerToMember,const Type & _rMemberType)159 void OColumn::registerProperty( const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, void* _pPointerToMember, const Type& _rMemberType )
160 {
161     ::comphelper::OPropertyContainer::registerProperty( _rName, _nHandle, _nAttributes, _pPointerToMember, _rMemberType );
162 }
163 
164 //------------------------------------------------------------------------------
registerMayBeVoidProperty(const::rtl::OUString & _rName,sal_Int32 _nHandle,sal_Int32 _nAttributes,Any * _pPointerToMember,const Type & _rExpectedType)165 void OColumn::registerMayBeVoidProperty( const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, Any* _pPointerToMember, const Type& _rExpectedType )
166 {
167     ::comphelper::OPropertyContainer::registerMayBeVoidProperty( _rName, _nHandle, _nAttributes, _pPointerToMember, _rExpectedType );
168 }
169 
170 //------------------------------------------------------------------------------
registerPropertyNoMember(const::rtl::OUString & _rName,sal_Int32 _nHandle,sal_Int32 _nAttributes,const Type & _rType,const void * _pInitialValue)171 void OColumn::registerPropertyNoMember( const ::rtl::OUString& _rName, sal_Int32 _nHandle, sal_Int32 _nAttributes, const Type& _rType, const void* _pInitialValue )
172 {
173     ::comphelper::OPropertyContainer::registerPropertyNoMember( _rName, _nHandle, _nAttributes, _rType, _pInitialValue );
174 }
175 
176 //============================================================
177 //= OColumns
178 //============================================================
179 DBG_NAME(OColumns);
180 
181 //--------------------------------------------------------------------------
OColumns(::cppu::OWeakObject & _rParent,::osl::Mutex & _rMutex,sal_Bool _bCaseSensitive,const::std::vector<::rtl::OUString> & _rVector,IColumnFactory * _pColFactory,::connectivity::sdbcx::IRefreshableColumns * _pRefresh,sal_Bool _bAddColumn,sal_Bool _bDropColumn,sal_Bool _bUseHardRef)182 OColumns::OColumns(::cppu::OWeakObject& _rParent,
183 				   ::osl::Mutex& _rMutex,
184 				   sal_Bool _bCaseSensitive,const ::std::vector< ::rtl::OUString> &_rVector,
185 				   IColumnFactory* _pColFactory,
186 				   ::connectivity::sdbcx::IRefreshableColumns* _pRefresh,
187 				   sal_Bool _bAddColumn,
188 				   sal_Bool _bDropColumn,
189 				   sal_Bool _bUseHardRef)
190 				   : OColumns_BASE(_rParent,_bCaseSensitive,_rMutex,_rVector,_bUseHardRef)
191 	,m_pMediator(NULL)
192 	,m_xDrvColumns(NULL)
193 	,m_pColFactoryImpl(_pColFactory)
194 	,m_pRefreshColumns(_pRefresh)
195 	,m_bInitialized(sal_False)
196 	,m_bAddColumn(_bAddColumn)
197 	,m_bDropColumn(_bDropColumn)
198 {
199 	DBG_CTOR(OColumns, NULL);
200 }
201 
202 // -------------------------------------------------------------------------
OColumns(::cppu::OWeakObject & _rParent,::osl::Mutex & _rMutex,const::com::sun::star::uno::Reference<::com::sun::star::container::XNameAccess> & _rxDrvColumns,sal_Bool _bCaseSensitive,const::std::vector<::rtl::OUString> & _rVector,IColumnFactory * _pColFactory,::connectivity::sdbcx::IRefreshableColumns * _pRefresh,sal_Bool _bAddColumn,sal_Bool _bDropColumn,sal_Bool _bUseHardRef)203 OColumns::OColumns(::cppu::OWeakObject& _rParent, ::osl::Mutex& _rMutex,
204 		const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& _rxDrvColumns,
205 		sal_Bool _bCaseSensitive,const ::std::vector< ::rtl::OUString> &_rVector,
206 		IColumnFactory* _pColFactory,
207 		::connectivity::sdbcx::IRefreshableColumns* _pRefresh,
208 		sal_Bool _bAddColumn,
209 		sal_Bool _bDropColumn,
210 		sal_Bool _bUseHardRef)
211 	   : OColumns_BASE(_rParent,_bCaseSensitive,_rMutex,_rVector,_bUseHardRef)
212 	,m_pMediator(NULL)
213 	,m_xDrvColumns(_rxDrvColumns)
214 	,m_pColFactoryImpl(_pColFactory)
215 	,m_pRefreshColumns(_pRefresh)
216 	,m_bInitialized(sal_False)
217 	,m_bAddColumn(_bAddColumn)
218 	,m_bDropColumn(_bDropColumn)
219 {
220 	DBG_CTOR(OColumns, NULL);
221 }
222 //--------------------------------------------------------------------------
~OColumns()223 OColumns::~OColumns()
224 {
225 	DBG_DTOR(OColumns, NULL);
226 }
227 
228 // XServiceInfo
229 //------------------------------------------------------------------------------
getImplementationName()230 rtl::OUString OColumns::getImplementationName(  ) throw(RuntimeException)
231 {
232 	return rtl::OUString::createFromAscii("com.sun.star.sdb.OColumns");
233 }
234 
235 //------------------------------------------------------------------------------
supportsService(const::rtl::OUString & _rServiceName)236 sal_Bool OColumns::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
237 {
238 	return ::comphelper::findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0;
239 }
240 
241 //------------------------------------------------------------------------------
getSupportedServiceNames()242 Sequence< ::rtl::OUString > OColumns::getSupportedServiceNames(  ) throw (RuntimeException)
243 {
244 	Sequence< ::rtl::OUString > aSNS( 1 );
245 	aSNS[0] = SERVICE_SDBCX_CONTAINER;
246 	return aSNS;
247 }
248 
249 //------------------------------------------------------------------
append(const::rtl::OUString & _rName,OColumn * _pColumn)250 void OColumns::append( const ::rtl::OUString& _rName, OColumn* _pColumn )
251 {
252 	MutexGuard aGuard(m_rMutex);
253 
254 	OSL_ENSURE( _pColumn, "OColumns::append: invalid column!" );
255 	OSL_ENSURE( !m_pElements->exists( _rName ),"OColumns::append: Column already exists");
256 
257 	_pColumn->m_sName = _rName;
258 
259 	// now really insert the column
260 	insertElement( _rName, _pColumn );
261 }
262 
263 //------------------------------------------------------------------
clearColumns()264 void OColumns::clearColumns()
265 {
266 	MutexGuard aGuard(m_rMutex);
267 	disposing();
268 }
269 
270 // -----------------------------------------------------------------------------
disposing(void)271 void SAL_CALL OColumns::disposing(void)
272 {
273 	MutexGuard aGuard(m_rMutex);
274 	m_xDrvColumns = NULL;
275 	m_pMediator = NULL;
276 	m_pColFactoryImpl = NULL;
277 	OColumns_BASE::disposing();
278 }
279 
280 // -------------------------------------------------------------------------
impl_refresh()281 void OColumns::impl_refresh() throw(::com::sun::star::uno::RuntimeException)
282 {
283 	if (m_pRefreshColumns)
284 		m_pRefreshColumns->refreshColumns();
285 }
286 
287 // -------------------------------------------------------------------------
createObject(const::rtl::OUString & _rName)288 connectivity::sdbcx::ObjectType OColumns::createObject(const ::rtl::OUString& _rName)
289 {
290 	OSL_ENSURE(m_pColFactoryImpl, "OColumns::createObject: no column factory!");
291 
292 	connectivity::sdbcx::ObjectType xRet;
293 	if ( m_pColFactoryImpl )
294 	{
295 		xRet = m_pColFactoryImpl->createColumn(_rName);
296 		Reference<XChild> xChild(xRet,UNO_QUERY);
297 		if ( xChild.is() )
298 			xChild->setParent(static_cast<XChild*>(static_cast<TXChild*>(this)));
299 	}
300 
301 	Reference<XPropertySet> xDest(xRet,UNO_QUERY);
302 	if ( m_pMediator && xDest.is() )
303 		m_pMediator->notifyElementCreated(_rName,xDest);
304 
305 	return xRet;
306 }
307 // -------------------------------------------------------------------------
createDescriptor()308 Reference< XPropertySet > OColumns::createDescriptor()
309 {
310 	if ( m_pColFactoryImpl )
311 	{
312 		Reference<XPropertySet> xRet = m_pColFactoryImpl->createColumnDescriptor();
313 		Reference<XChild> xChild(xRet,UNO_QUERY);
314 		if ( xChild.is() )
315 			xChild->setParent(static_cast<XChild*>(static_cast<TXChild*>(this)));
316 		return xRet;
317 	}
318 	else
319 		return Reference< XPropertySet >();
320 }
321 // -------------------------------------------------------------------------
queryInterface(const Type & rType)322 Any SAL_CALL OColumns::queryInterface( const Type & rType ) throw(RuntimeException)
323 {
324 	Any aRet;
325 	if(m_xDrvColumns.is())
326 	{
327 		aRet = m_xDrvColumns->queryInterface(rType);
328 		if ( aRet.hasValue() )
329 			aRet = OColumns_BASE::queryInterface( rType);
330 		if ( !aRet.hasValue() )
331 			aRet = TXChild::queryInterface( rType);
332 		return aRet;
333 	}
334 	else if(!m_pTable || (m_pTable && !m_pTable->isNew()))
335 	{
336 		if(!m_bAddColumn	&& rType == getCppuType( (Reference<XAppend>*)0))
337 			return Any();
338 		if(!m_bDropColumn	&& rType == getCppuType( (Reference<XDrop>*)0))
339 			return Any();
340 	}
341 
342 	aRet = OColumns_BASE::queryInterface( rType);
343 	if ( !aRet.hasValue() )
344 		aRet = TXChild::queryInterface( rType);
345 	return aRet;
346 }
347 // -------------------------------------------------------------------------
getTypes()348 Sequence< Type > SAL_CALL OColumns::getTypes(  ) throw(RuntimeException)
349 {
350 	sal_Bool bAppendFound = sal_False,bDropFound = sal_False;
351 
352 	sal_Int32 nSize = 0;
353 	Type aAppendType = getCppuType( (Reference<XAppend>*)0);
354 	Type aDropType	 = getCppuType( (Reference<XDrop>*)0);
355 	if(m_xDrvColumns.is())
356 	{
357 		Reference<XTypeProvider> xTypes(m_xDrvColumns,UNO_QUERY);
358 		Sequence< Type > aTypes(xTypes->getTypes());
359 
360 		Sequence< Type > aSecTypes(OColumns_BASE::getTypes());
361 
362 
363 		const Type* pBegin = aTypes.getConstArray();
364 		const Type* pEnd = pBegin + aTypes.getLength();
365 		for (;pBegin != pEnd ; ++pBegin)
366 		{
367 			if(aAppendType == *pBegin)
368 				bAppendFound = sal_True;
369 			else if(aDropType == *pBegin)
370 				bDropFound = sal_True;
371 		}
372 		nSize = (bDropFound ? (bAppendFound ? 0 : 1) : (bAppendFound ? 1 : 2));
373 	}
374 	else
375 	{
376 		nSize = ((m_pTable && m_pTable->isNew()) ? 0 :
377 					((m_bDropColumn ?
378 						(m_bAddColumn ? 0 : 1) : (m_bAddColumn ? 1 : 2))));
379 		bDropFound		= (m_pTable && m_pTable->isNew()) || m_bDropColumn;
380 		bAppendFound	= (m_pTable && m_pTable->isNew()) || m_bAddColumn;
381 	}
382 	Sequence< Type > aTypes(::comphelper::concatSequences(OColumns_BASE::getTypes(),TXChild::getTypes()));
383 	Sequence< Type > aRet(aTypes.getLength() - nSize);
384 
385 	const Type* pBegin = aTypes.getConstArray();
386 	const Type* pEnd = pBegin + aTypes.getLength();
387 	for(sal_Int32 i=0;pBegin != pEnd ;++pBegin)
388 	{
389 		if(*pBegin != aAppendType && *pBegin != aDropType)
390 			aRet.getArray()[i++] = *pBegin;
391 		else if(bDropFound && *pBegin == aDropType)
392 			aRet.getArray()[i++] = *pBegin;
393 		else if(bAppendFound && *pBegin == aAppendType)
394 			aRet.getArray()[i++] = *pBegin;
395 	}
396 	return aRet;
397 }
398 // -------------------------------------------------------------------------
399 // XAppend
appendObject(const::rtl::OUString & _rForName,const Reference<XPropertySet> & descriptor)400 sdbcx::ObjectType OColumns::appendObject( const ::rtl::OUString& _rForName, const Reference< XPropertySet >& descriptor )
401 {
402     sdbcx::ObjectType xReturn;
403 
404     Reference< XAppend > xAppend( m_xDrvColumns, UNO_QUERY );
405 	if ( xAppend.is() )
406 	{
407 		xAppend->appendByDescriptor(descriptor);
408         xReturn = createObject( _rForName );
409 	}
410     else if ( m_pTable && !m_pTable->isNew() )
411     {
412         if ( m_bAddColumn )
413         {
414             Reference< ::com::sun::star::sdb::tools::XTableAlteration> xAlterService = m_pTable->getAlterService();
415             if ( xAlterService.is() )
416             {
417                 xAlterService->addColumn(m_pTable,descriptor);
418                 xReturn = createObject( _rForName );
419             }
420             else
421                 xReturn = OColumns_BASE::appendObject( _rForName, descriptor );
422         }
423         else
424             ::dbtools::throwGenericSQLException( DBA_RES( RID_STR_NO_COLUMN_ADD ), static_cast<XChild*>(static_cast<TXChild*>(this)) );
425     }
426     else
427         xReturn = cloneDescriptor( descriptor );
428 
429     if ( m_pColFactoryImpl )
430 		m_pColFactoryImpl->columnAppended( descriptor );
431 
432     ::dbaccess::notifyDataSourceModified(m_xParent,sal_True);
433 
434     return xReturn;
435 }
436 // -------------------------------------------------------------------------
437 // XDrop
dropObject(sal_Int32 _nPos,const::rtl::OUString _sElementName)438 void OColumns::dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName)
439 {
440 	Reference< XDrop > xDrop( m_xDrvColumns, UNO_QUERY );
441 	if ( xDrop.is() )
442 	{
443 		xDrop->dropByName( _sElementName );
444 	}
445 	else if ( m_pTable && !m_pTable->isNew() )
446     {
447         if ( m_bDropColumn )
448         {
449             Reference< ::com::sun::star::sdb::tools::XTableAlteration> xAlterService = m_pTable->getAlterService();
450             if ( xAlterService.is() )
451                 xAlterService->dropColumn(m_pTable,_sElementName);
452             else
453 		        OColumns_BASE::dropObject(_nPos,_sElementName);
454         }
455         else
456             ::dbtools::throwGenericSQLException( DBA_RES( RID_STR_NO_COLUMN_DROP ), static_cast<XChild*>(static_cast<TXChild*>(this)) );
457     }
458 
459     if ( m_pColFactoryImpl )
460 		m_pColFactoryImpl->columnDropped(_sElementName);
461 
462     ::dbaccess::notifyDataSourceModified(m_xParent,sal_True);
463 }
464 // -----------------------------------------------------------------------------
465 
getParent()466 Reference< XInterface > SAL_CALL OColumns::getParent(  ) throw (RuntimeException)
467 {
468 	::osl::MutexGuard aGuard(m_rMutex);
469 	return m_xParent;
470 }
471 // -----------------------------------------------------------------------------
setParent(const Reference<XInterface> & _xParent)472 void SAL_CALL OColumns::setParent( const Reference< XInterface >& _xParent ) throw (NoSupportException, RuntimeException)
473 {
474 	::osl::MutexGuard aGuard(m_rMutex);
475 	m_xParent = _xParent;
476 }
477 // -----------------------------------------------------------------------------
478