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 "apitools.hxx"
28 #include "dbastrings.hrc"
29 #include "definitioncolumn.hxx"
30 #include "sdbcoretools.hxx"
31 
32 /** === begin UNO includes === **/
33 #include <com/sun/star/beans/PropertyAttribute.hpp>
34 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
35 /** === end UNO includes === **/
36 
37 #include <comphelper/property.hxx>
38 #include <comphelper/types.hxx>
39 #include <connectivity/dbtools.hxx>
40 #include <cppuhelper/typeprovider.hxx>
41 #include <tools/debug.hxx>
42 #include <tools/diagnose_ex.h>
43 
44 using namespace ::com::sun::star::sdbc;
45 using namespace ::com::sun::star::sdbcx;
46 using namespace ::com::sun::star::beans;
47 using namespace ::com::sun::star::uno;
48 using namespace ::com::sun::star::lang;
49 using namespace ::com::sun::star::container;
50 using namespace ::cppu;
51 using namespace ::comphelper;
52 using namespace ::osl;
53 using namespace dbaccess;
54 
55 #define HAS_DESCRIPTION		        0x00000001
56 #define HAS_DEFAULTVALUE	        0x00000002
57 #define HAS_ROWVERSION		        0x00000004
58 #define HAS_AUTOINCREMENT_CREATION	0x00000008
59 
60 //============================================================
61 //= OTableColumnDescriptor
62 //============================================================
63 IMPLEMENT_FORWARD_XINTERFACE2(OTableColumnDescriptor,OColumn,TXChild)
64 
65 //------------------------------------------------------------------------------
66 void OTableColumnDescriptor::impl_registerProperties()
67 {
68     sal_Int32 nDefaultAttr = m_bActAsDescriptor ? 0 : PropertyAttribute::READONLY;
69 
70     registerProperty( PROPERTY_TYPENAME, PROPERTY_ID_TYPENAME, nDefaultAttr, &m_aTypeName, ::getCppuType( &m_aTypeName ) );
71     registerProperty( PROPERTY_DESCRIPTION, PROPERTY_ID_DESCRIPTION, nDefaultAttr, &m_aDescription, ::getCppuType( &m_aDescription ) );
72     registerProperty( PROPERTY_DEFAULTVALUE, PROPERTY_ID_DEFAULTVALUE, nDefaultAttr, &m_aDefaultValue, ::getCppuType( &m_aDefaultValue ) );
73 
74     if ( m_bActAsDescriptor )
75         registerProperty( PROPERTY_AUTOINCREMENTCREATION, PROPERTY_ID_AUTOINCREMENTCREATION, nDefaultAttr, &m_aAutoIncrementValue, ::getCppuType( &m_aAutoIncrementValue ) );
76 
77     registerProperty( PROPERTY_TYPE, PROPERTY_ID_TYPE, nDefaultAttr, &m_nType, ::getCppuType( &m_nType ) );
78     registerProperty( PROPERTY_PRECISION, PROPERTY_ID_PRECISION, nDefaultAttr, &m_nPrecision, ::getCppuType( &m_nPrecision ) );
79     registerProperty( PROPERTY_SCALE, PROPERTY_ID_SCALE, nDefaultAttr, &m_nScale, ::getCppuType( &m_nScale ) );
80     registerProperty( PROPERTY_ISNULLABLE, PROPERTY_ID_ISNULLABLE, nDefaultAttr, &m_nIsNullable, ::getCppuType( &m_nIsNullable ) );
81     registerProperty( PROPERTY_ISAUTOINCREMENT, PROPERTY_ID_ISAUTOINCREMENT, nDefaultAttr, &m_bAutoIncrement, ::getCppuType( &m_bAutoIncrement ) );
82     registerProperty( PROPERTY_ISROWVERSION, PROPERTY_ID_ISROWVERSION, nDefaultAttr, &m_bRowVersion, ::getCppuType( &m_bRowVersion ) );
83     registerProperty( PROPERTY_ISCURRENCY, PROPERTY_ID_ISCURRENCY, nDefaultAttr, &m_bCurrency, ::getCppuType( &m_bCurrency ) );
84 
85     OColumnSettings::registerProperties( *this );
86 }
87 
88 //--------------------------------------------------------------------------
89 IMPLEMENT_GET_IMPLEMENTATION_ID( OTableColumnDescriptor )
90 
91 // ::com::sun::star::lang::XServiceInfo
92 //------------------------------------------------------------------------------
93 rtl::OUString OTableColumnDescriptor::getImplementationName(  ) throw (RuntimeException)
94 {
95 	return rtl::OUString::createFromAscii("com.sun.star.sdb.OTableColumnDescriptor");
96 }
97 
98 //------------------------------------------------------------------------------
99 Sequence< ::rtl::OUString > OTableColumnDescriptor::getSupportedServiceNames(  ) throw (RuntimeException)
100 {
101 	Sequence< ::rtl::OUString > aSNS( 2 );
102     aSNS[0] = m_bActAsDescriptor ? SERVICE_SDBCX_COLUMNDESCRIPTOR : SERVICE_SDBCX_COLUMN;
103 	aSNS[1] = SERVICE_SDB_COLUMNSETTINGS;
104 	return aSNS;
105 }
106 
107 // comphelper::OPropertyArrayUsageHelper
108 //------------------------------------------------------------------------------
109 ::cppu::IPropertyArrayHelper* OTableColumnDescriptor::createArrayHelper( ) const
110 {
111     Sequence< Property > aProps;
112     describeProperties( aProps );
113     return new ::cppu::OPropertyArrayHelper( aProps );
114 }
115 
116 // cppu::OPropertySetHelper
117 //------------------------------------------------------------------------------
118 ::cppu::IPropertyArrayHelper& OTableColumnDescriptor::getInfoHelper()
119 {
120 	return *static_cast< ::comphelper::OPropertyArrayUsageHelper< OTableColumnDescriptor >* >(this)->getArrayHelper();
121 }
122 
123 //------------------------------------------------------------------------------
124 void OTableColumnDescriptor::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception)
125 {
126 	OColumn::setFastPropertyValue_NoBroadcast( nHandle, rValue );
127 	::dbaccess::notifyDataSourceModified( m_xParent, sal_True );
128 }
129 
130 // -----------------------------------------------------------------------------
131 Reference< XInterface > SAL_CALL OTableColumnDescriptor::getParent(  ) throw (RuntimeException)
132 {
133 	::osl::MutexGuard aGuard(m_aMutex);
134 	return m_xParent;
135 }
136 // -----------------------------------------------------------------------------
137 void SAL_CALL OTableColumnDescriptor::setParent( const Reference< XInterface >& _xParent ) throw (NoSupportException, RuntimeException)
138 {
139 	::osl::MutexGuard aGuard(m_aMutex);
140 	m_xParent = _xParent;
141 }
142 //============================================================
143 //= OTableColumn
144 //============================================================
145 DBG_NAME(OTableColumn);
146 
147 // -------------------------------------------------------------------------
148 OTableColumn::OTableColumn( const ::rtl::OUString& _rName )
149     :OTableColumnDescriptor( false /* do not act as descriptor */ )
150 {
151 	DBG_CTOR(OTableColumn,NULL);
152 	m_sName = _rName;
153 }
154 
155 // -----------------------------------------------------------------------------
156 OTableColumn::~OTableColumn()
157 {
158 	DBG_DTOR(OTableColumn,NULL);
159 }
160 
161 //--------------------------------------------------------------------------
162 IMPLEMENT_GET_IMPLEMENTATION_ID( OTableColumn )
163 
164 //------------------------------------------------------------------------------
165 rtl::OUString OTableColumn::getImplementationName(  ) throw (RuntimeException)
166 {
167 	return rtl::OUString::createFromAscii("com.sun.star.sdb.OTableColumn");
168 }
169 
170 //------------------------------------------------------------------------------
171 ::cppu::IPropertyArrayHelper& SAL_CALL OTableColumn::getInfoHelper()
172 {
173     return *OTableColumn_PBase::getArrayHelper();
174 }
175 
176 //------------------------------------------------------------------------------
177 ::cppu::IPropertyArrayHelper* OTableColumn::createArrayHelper( ) const
178 {
179     return OTableColumnDescriptor::createArrayHelper();
180 }
181 
182 // =========================================================================
183 //= OQueryColumn
184 // =========================================================================
185 DBG_NAME( OQueryColumn );
186 
187 // -------------------------------------------------------------------------
188 OQueryColumn::OQueryColumn( const Reference< XPropertySet >& _rxParserColumn, const Reference< XConnection >& _rxConnection,const ::rtl::OUString i_sLabel )
189     :OTableColumnDescriptor( false /* do not act as descriptor */ )
190     ,m_sLabel(i_sLabel)
191 {
192     const sal_Int32 nPropAttr = PropertyAttribute::READONLY;
193     registerProperty( PROPERTY_CATALOGNAME, PROPERTY_ID_CATALOGNAME, nPropAttr, &m_sCatalogName, ::getCppuType( &m_sCatalogName ) );
194     registerProperty( PROPERTY_SCHEMANAME, PROPERTY_ID_SCHEMANAME, nPropAttr, &m_sSchemaName, ::getCppuType( &m_sSchemaName ) );
195     registerProperty( PROPERTY_TABLENAME, PROPERTY_ID_TABLENAME, nPropAttr, &m_sTableName, ::getCppuType( &m_sTableName ) );
196     registerProperty( PROPERTY_REALNAME, PROPERTY_ID_REALNAME, nPropAttr, &m_sRealName, ::getCppuType( &m_sRealName ) );
197     registerProperty( PROPERTY_LABEL, PROPERTY_ID_LABEL, nPropAttr, &m_sLabel, ::getCppuType( &m_sLabel ) );
198 
199 	DBG_CTOR( OQueryColumn, NULL );
200 
201     OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_TYPENAME ) >>= m_aTypeName );
202     OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_ISNULLABLE ) >>= m_nIsNullable );
203 	OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_PRECISION ) >>= m_nPrecision );
204 	OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_SCALE ) >>= m_nScale );
205 	OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_TYPE ) >>= m_nType );
206     OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_ISAUTOINCREMENT ) >>= m_bAutoIncrement );
207     OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_ISCURRENCY ) >>= m_bCurrency );
208 	OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_NAME ) >>= m_sName );
209 
210     m_bRowVersion = sal_False;
211 
212     Reference< XPropertySetInfo > xPSI( _rxParserColumn->getPropertySetInfo(), UNO_SET_THROW );
213     if ( xPSI->hasPropertyByName( PROPERTY_DEFAULTVALUE ) )
214         OSL_VERIFY( _rxParserColumn->getPropertyValue( PROPERTY_DEFAULTVALUE ) >>= m_aDefaultValue );
215 
216     // copy some optional properties from the parser column
217     struct PropertyDescriptor
218     {
219         ::rtl::OUString sName;
220         sal_Int32       nHandle;
221     };
222     PropertyDescriptor aProps[] =
223     {
224         { PROPERTY_CATALOGNAME,      PROPERTY_ID_CATALOGNAME },
225         { PROPERTY_SCHEMANAME,       PROPERTY_ID_SCHEMANAME },
226         { PROPERTY_TABLENAME,        PROPERTY_ID_TABLENAME },
227         { PROPERTY_REALNAME,         PROPERTY_ID_REALNAME }
228     };
229     for ( size_t i=0; i < sizeof( aProps ) / sizeof( aProps[0] ); ++i )
230     {
231         if ( xPSI->hasPropertyByName( aProps[i].sName ) )
232             setFastPropertyValue_NoBroadcast( aProps[i].nHandle, _rxParserColumn->getPropertyValue( aProps[i].sName ) );
233     }
234 
235     // determine the table column we're based on
236     osl_incrementInterlockedCount( &m_refCount );
237     {
238         m_xOriginalTableColumn = impl_determineOriginalTableColumn( _rxConnection );
239     }
240     osl_decrementInterlockedCount( &m_refCount );
241 }
242 
243 //--------------------------------------------------------------------------
244 OQueryColumn::~OQueryColumn()
245 {
246     DBG_DTOR( OQueryColumn, NULL );
247 }
248 
249 //--------------------------------------------------------------------------
250 Reference< XPropertySet > OQueryColumn::impl_determineOriginalTableColumn( const Reference< XConnection >& _rxConnection )
251 {
252     OSL_PRECOND( _rxConnection.is(), "OQueryColumn::impl_determineOriginalTableColumn: illegal connection!" );
253     if ( !_rxConnection.is() )
254         return NULL;
255 
256     Reference< XPropertySet > xOriginalTableColumn;
257     try
258     {
259         // determine the composed table name, plus the column name, as indicated by the
260         // respective properties
261         ::rtl::OUString sCatalog, sSchema, sTable;
262         OSL_VERIFY( getPropertyValue( PROPERTY_CATALOGNAME ) >>= sCatalog );
263         OSL_VERIFY( getPropertyValue( PROPERTY_SCHEMANAME ) >>= sSchema );
264         OSL_VERIFY( getPropertyValue( PROPERTY_TABLENAME ) >>= sTable );
265         if ( !sCatalog.getLength() && !sSchema.getLength() && !sTable.getLength() )
266             return NULL;
267 
268         ::rtl::OUString sComposedTableName = ::dbtools::composeTableName(
269             _rxConnection->getMetaData(), sCatalog, sSchema, sTable, sal_False, ::dbtools::eComplete );
270 
271         // retrieve the table in question
272         Reference< XTablesSupplier > xSuppTables( _rxConnection, UNO_QUERY_THROW );
273         Reference< XNameAccess > xTables( xSuppTables->getTables(), UNO_QUERY_THROW );
274         if ( !xTables->hasByName( sComposedTableName ) )
275             return NULL;
276 
277         Reference< XColumnsSupplier > xSuppCols( xTables->getByName( sComposedTableName ), UNO_QUERY_THROW );
278         Reference< XNameAccess > xColumns( xSuppCols->getColumns(), UNO_QUERY_THROW );
279 
280         ::rtl::OUString sColumn;
281         OSL_VERIFY( getPropertyValue( PROPERTY_REALNAME ) >>= sColumn );
282         if ( !xColumns->hasByName( sColumn ) )
283             return NULL;
284 
285         xOriginalTableColumn.set( xColumns->getByName( sColumn ), UNO_QUERY );
286     }
287     catch( const Exception& )
288     {
289     	DBG_UNHANDLED_EXCEPTION();
290     }
291     return xOriginalTableColumn;
292 }
293 
294 //--------------------------------------------------------------------------
295 IMPLEMENT_GET_IMPLEMENTATION_ID( OQueryColumn )
296 
297 //--------------------------------------------------------------------------
298 ::rtl::OUString SAL_CALL OQueryColumn::getImplementationName(  ) throw(RuntimeException)
299 {
300     return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.dbaccess.OQueryColumn" ) );
301 }
302 
303 //------------------------------------------------------------------------------
304 ::cppu::IPropertyArrayHelper& SAL_CALL OQueryColumn::getInfoHelper()
305 {
306     return *OQueryColumn_PBase::getArrayHelper();
307 }
308 
309 //--------------------------------------------------------------------------
310 ::cppu::IPropertyArrayHelper* OQueryColumn::createArrayHelper() const
311 {
312     return OTableColumnDescriptor::createArrayHelper();
313 }
314 
315 //--------------------------------------------------------------------------
316 void SAL_CALL OQueryColumn::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const
317 {
318     OTableColumnDescriptor::getFastPropertyValue( _rValue, _nHandle );
319 
320     // special treatment for column settings:
321     if ( !OColumnSettings::isColumnSettingProperty( _nHandle ) )
322         return;
323 
324     // If the setting has its default value, then try to obtain the value from the table column which
325     // this query column is based on
326     if ( !OColumnSettings::isDefaulted( _nHandle, _rValue ) )
327         return;
328 
329     if ( !m_xOriginalTableColumn.is() )
330         return;
331 
332     try
333     {
334         // determine original property name
335         ::rtl::OUString sPropName;
336         sal_Int16 nAttributes( 0 );
337         const_cast< OQueryColumn* >( this )->getInfoHelper().fillPropertyMembersByHandle( &sPropName, &nAttributes, _nHandle );
338         OSL_ENSURE( sPropName.getLength(), "OColumnWrapper::impl_getPropertyNameFromHandle: property not found!" );
339 
340         _rValue = m_xOriginalTableColumn->getPropertyValue( sPropName );
341     }
342     catch( const Exception& )
343     {
344     	DBG_UNHANDLED_EXCEPTION();
345     }
346 }
347 
348 //==========================================================================
349 //= OColumnWrapper
350 //==========================================================================
351 DBG_NAME(OColumnWrapper);
352 //--------------------------------------------------------------------------
353 OColumnWrapper::OColumnWrapper( const Reference< XPropertySet > & rCol, const bool _bNameIsReadOnly )
354     :OColumn( _bNameIsReadOnly )
355     ,m_xAggregate(rCol)
356     ,m_nColTypeID(-1)
357 {
358 	DBG_CTOR(OColumnWrapper,NULL);
359 	// which type of aggregate property do we have?
360     // we distingish the properties by the containment of optional properties
361 	m_nColTypeID = 0;
362 	if ( m_xAggregate.is() )
363 	{
364 		Reference <XPropertySetInfo > xInfo(m_xAggregate->getPropertySetInfo());
365 		m_nColTypeID |= xInfo->hasPropertyByName(PROPERTY_DESCRIPTION) ? HAS_DESCRIPTION : 0;
366 		m_nColTypeID |= xInfo->hasPropertyByName(PROPERTY_DEFAULTVALUE) ? HAS_DEFAULTVALUE : 0;
367 		m_nColTypeID |= xInfo->hasPropertyByName(PROPERTY_ISROWVERSION) ? HAS_ROWVERSION : 0;
368         m_nColTypeID |= xInfo->hasPropertyByName(PROPERTY_AUTOINCREMENTCREATION) ? HAS_AUTOINCREMENT_CREATION : 0;
369 
370 		m_xAggregate->getPropertyValue(PROPERTY_NAME) >>= m_sName;
371 	}
372 }
373 // -----------------------------------------------------------------------------
374 OColumnWrapper::~OColumnWrapper()
375 {
376 	DBG_DTOR(OColumnWrapper,NULL);
377 }
378 
379 //------------------------------------------------------------------------------
380 ::rtl::OUString OColumnWrapper::impl_getPropertyNameFromHandle( const sal_Int32 _nHandle ) const
381 {
382     ::rtl::OUString sPropName;
383     sal_Int16 nAttributes( 0 );
384     const_cast< OColumnWrapper* >( this )->getInfoHelper().fillPropertyMembersByHandle( &sPropName, &nAttributes, _nHandle );
385     OSL_ENSURE( sPropName.getLength(), "OColumnWrapper::impl_getPropertyNameFromHandle: property not found!" );
386     return sPropName;
387 }
388 
389 //------------------------------------------------------------------------------
390 void OColumnWrapper::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
391 {
392     // derived classes are free to either use the OPropertyContainer(Helper) mechanisms for properties,
393     // or to declare additional properties which are to be forwarded to the wrapped object. So we need
394     // to distinguish those cases.
395     if ( OColumn::isRegisteredProperty( nHandle ) )
396     {
397         OColumn::getFastPropertyValue( rValue, nHandle );
398     }
399     else
400     {
401 	    rValue = m_xAggregate->getPropertyValue( impl_getPropertyNameFromHandle( nHandle ) );
402 	}
403 }
404 
405 //------------------------------------------------------------------------------
406 sal_Bool OColumnWrapper::convertFastPropertyValue( Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle,
407             const Any& rValue ) throw (IllegalArgumentException)
408 {
409     sal_Bool bModified( sal_False );
410     if ( OColumn::isRegisteredProperty( nHandle ) )
411     {
412 	    bModified = OColumn::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue );
413     }
414     else
415     {
416         getFastPropertyValue( rOldValue, nHandle );
417         if ( rOldValue != rValue )
418         {
419             rConvertedValue = rValue;
420             bModified = sal_True;
421         }
422     }
423 	return bModified;
424 }
425 
426 //------------------------------------------------------------------------------
427 void OColumnWrapper::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception)
428 {
429     if ( OColumn::isRegisteredProperty( nHandle ) )
430     {
431 	    OColumn::setFastPropertyValue_NoBroadcast( nHandle, rValue );
432     }
433     else
434     {
435         m_xAggregate->setPropertyValue( impl_getPropertyNameFromHandle( nHandle ), rValue );
436     }
437 }
438 
439 // -----------------------------------------------------------------------------
440 sal_Int64 SAL_CALL OColumnWrapper::getSomething( const Sequence< sal_Int8 >& aIdentifier ) throw(RuntimeException)
441 {
442 	Reference< XUnoTunnel > xTunnel( m_xAggregate, UNO_QUERY);
443 	if ( xTunnel.is() )
444 		return xTunnel->getSomething( aIdentifier );
445 	return 0;
446 }
447 
448 //============================================================
449 //= OTableColumnDescriptorWrapper
450 //============================================================
451 //--------------------------------------------------------------------------
452 OTableColumnDescriptorWrapper::OTableColumnDescriptorWrapper( const Reference< XPropertySet >& _rCol, const bool _bPureWrap, const bool _bIsDescriptor )
453     :OColumnWrapper( _rCol, !_bIsDescriptor )
454     ,m_bPureWrap( _bPureWrap )
455     ,m_bIsDescriptor( _bIsDescriptor )
456 {
457     // let the ColumnSettings register its properties
458     OColumnSettings::registerProperties( *this );
459 }
460 
461 // com::sun::star::lang::XTypeProvider
462 //--------------------------------------------------------------------------
463 IMPLEMENT_GET_IMPLEMENTATION_ID( OTableColumnDescriptorWrapper )
464 
465 // ::com::sun::star::lang::XServiceInfo
466 //------------------------------------------------------------------------------
467 rtl::OUString OTableColumnDescriptorWrapper::getImplementationName(  ) throw (RuntimeException)
468 {
469 	return rtl::OUString::createFromAscii("com.sun.star.sdb.OTableColumnDescriptorWrapper");
470 }
471 
472 //------------------------------------------------------------------------------
473 Sequence< ::rtl::OUString > OTableColumnDescriptorWrapper::getSupportedServiceNames(  ) throw (RuntimeException)
474 {
475 	Sequence< ::rtl::OUString > aSNS( 2 );
476 	aSNS[0] = SERVICE_SDBCX_COLUMNDESCRIPTOR;
477 	aSNS[1] = SERVICE_SDB_COLUMNSETTINGS;
478 	return aSNS;
479 }
480 
481 // comphelper::OPropertyArrayUsageHelper
482 //------------------------------------------------------------------------------
483 ::cppu::IPropertyArrayHelper* OTableColumnDescriptorWrapper::createArrayHelper( sal_Int32 nId ) const
484 {
485     const sal_Int32 nHaveAlways = 7;
486 
487 	// Which optional properties are contained?
488 	sal_Int32 nHaveOptionally = 0;
489 	if (nId & HAS_DESCRIPTION)
490 		++nHaveOptionally;
491 	if (nId & HAS_DEFAULTVALUE)
492 		++nHaveOptionally;
493 	if (nId & HAS_ROWVERSION)
494 		++nHaveOptionally;
495     if ( nId & HAS_AUTOINCREMENT_CREATION )
496 		++nHaveOptionally;
497 
498     const sal_Int32 nPropertyCount( nHaveAlways + nHaveOptionally );
499 	Sequence< Property > aTableDescProperties( nPropertyCount );
500 	Property* pDesc = aTableDescProperties.getArray();
501 	sal_Int32 nPos = 0;
502 
503 	DECL_PROP0_BOOL( ISAUTOINCREMENT                );
504 	DECL_PROP0_BOOL( ISCURRENCY                     );
505 	DECL_PROP0( ISNULLABLE,         sal_Int32       );
506 	DECL_PROP0( PRECISION,          sal_Int32		);
507 	DECL_PROP0( SCALE,              sal_Int32		);
508 	DECL_PROP0( TYPE,               sal_Int32		);
509 	DECL_PROP0( TYPENAME,           ::rtl::OUString );
510 
511     if ( nId & HAS_AUTOINCREMENT_CREATION )
512 	{
513 		DECL_PROP1( AUTOINCREMENTCREATION, ::rtl::OUString, MAYBEVOID );
514 	}
515 	if ( nId & HAS_DEFAULTVALUE )
516 	{
517 		DECL_PROP0( DEFAULTVALUE, ::rtl::OUString );
518 	}
519 	if ( nId & HAS_DESCRIPTION )
520 	{
521 		DECL_PROP0( DESCRIPTION, ::rtl::OUString );
522 	}
523 	if ( nId & HAS_ROWVERSION )
524 	{
525 		DECL_PROP0_BOOL( ISROWVERSION );
526 	}
527 
528     OSL_ENSURE( nPos == nPropertyCount, "OTableColumnDescriptorWrapper::createArrayHelper: something went wrong!" );
529 
530     if ( !m_bIsDescriptor )
531     {
532         for (   Property* prop = aTableDescProperties.getArray();
533                 prop != aTableDescProperties.getArray() + aTableDescProperties.getLength();
534                 ++prop
535             )
536         {
537             prop->Attributes |= PropertyAttribute::READONLY;
538         }
539     }
540 
541     // finally also describe the properties which are maintained by our base class, in particular the OPropertyContainerHelper
542     Sequence< Property > aBaseProperties;
543     describeProperties( aBaseProperties );
544 
545     Sequence< Property > aAllProperties( ::comphelper::concatSequences( aTableDescProperties, aBaseProperties ) );
546 	return new ::cppu::OPropertyArrayHelper( aAllProperties, sal_False );
547 }
548 
549 // cppu::OPropertySetHelper
550 //------------------------------------------------------------------------------
551 ::cppu::IPropertyArrayHelper& OTableColumnDescriptorWrapper::getInfoHelper()
552 {
553 	return *static_cast< OIdPropertyArrayUsageHelper< OTableColumnDescriptorWrapper >* >(this)->getArrayHelper(m_nColTypeID);
554 }
555 
556 //------------------------------------------------------------------------------
557 void OTableColumnDescriptorWrapper::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
558 {
559 	if ( m_bPureWrap )
560 	{
561 		rValue = m_xAggregate->getPropertyValue( impl_getPropertyNameFromHandle( nHandle ) );
562 	}
563 	else
564 	{
565 	    OColumnWrapper::getFastPropertyValue( rValue, nHandle );
566 	}
567 }
568 
569 //------------------------------------------------------------------------------
570 sal_Bool OTableColumnDescriptorWrapper::convertFastPropertyValue( Any & rConvertedValue, Any & rOldValue, sal_Int32 nHandle, const Any& rValue ) throw (IllegalArgumentException)
571 {
572 	sal_Bool bModified(sal_False);
573 	if ( m_bPureWrap )
574     {
575         // do not delegate to OColumnWrapper: It would, for the properties which were registered with registerProperty,
576         // ask the OPropertyContainer base class, which is not what we want here.
577         // TODO: the whole "m_bPureWrap"-thingie is strange. We should have a dedicated class doing this wrapping,
578         // not a class which normally serves other purposes, and only sometimes does a "pure wrap". It makes the
579         // code unnecessarily hard to maintain, and error prone.
580         rOldValue = m_xAggregate->getPropertyValue( impl_getPropertyNameFromHandle( nHandle ) );
581         if ( rOldValue != rValue )
582         {
583             rConvertedValue = rValue;
584             bModified = sal_True;
585         }
586     }
587 	else
588 	{
589         bModified = OColumnWrapper::convertFastPropertyValue( rConvertedValue, rOldValue, nHandle, rValue );
590 	}
591 	return bModified;
592 }
593 
594 //------------------------------------------------------------------------------
595 void OTableColumnDescriptorWrapper::setFastPropertyValue_NoBroadcast(
596 												sal_Int32 nHandle,
597 												const Any& rValue
598 												 )
599 												 throw (Exception)
600 {
601 	if ( m_bPureWrap )
602     {
603         m_xAggregate->setPropertyValue( impl_getPropertyNameFromHandle( nHandle ), rValue );
604     }
605 	else
606 	{
607 	    OColumnWrapper::setFastPropertyValue_NoBroadcast( nHandle, rValue );
608     }
609 }
610 
611 //============================================================
612 //= OTableColumnWrapper
613 //============================================================
614 //--------------------------------------------------------------------------
615 OTableColumnWrapper::OTableColumnWrapper( const Reference< XPropertySet >& rCol, const Reference< XPropertySet >& _xColDefintion,
616             const bool _bPureWrap )
617 	:OTableColumnDescriptorWrapper( rCol, _bPureWrap, false )
618 {
619 	osl_incrementInterlockedCount( &m_refCount );
620 	if ( _xColDefintion.is() )
621 	{
622 		try
623 		{
624 			::comphelper::copyProperties( _xColDefintion, this );
625 		}
626 		catch( const Exception& )
627 		{
628             DBG_UNHANDLED_EXCEPTION();
629 		}
630 	}
631 	osl_decrementInterlockedCount( &m_refCount );
632 }
633 
634 //--------------------------------------------------------------------------
635 OTableColumnWrapper::~OTableColumnWrapper()
636 {
637 }
638 
639 //--------------------------------------------------------------------------
640 IMPLEMENT_GET_IMPLEMENTATION_ID( OTableColumnWrapper )
641 
642 //------------------------------------------------------------------------------
643 rtl::OUString OTableColumnWrapper::getImplementationName(  ) throw (RuntimeException)
644 {
645 	return rtl::OUString::createFromAscii( "com.sun.star.sdb.OTableColumnWrapper" );
646 }
647 
648 //------------------------------------------------------------------------------
649 Sequence< ::rtl::OUString > OTableColumnWrapper::getSupportedServiceNames(  ) throw (RuntimeException)
650 {
651 	Sequence< ::rtl::OUString > aSNS( 2 );
652 	aSNS[0] = SERVICE_SDBCX_COLUMN;
653 	aSNS[1] = SERVICE_SDB_COLUMNSETTINGS;
654 	return aSNS;
655 }
656 
657 //------------------------------------------------------------------------------
658 ::cppu::IPropertyArrayHelper& OTableColumnWrapper::getInfoHelper()
659 {
660 	return *static_cast< OIdPropertyArrayUsageHelper< OTableColumnWrapper >* >(this)->getArrayHelper(m_nColTypeID);
661 }
662 
663 // comphelper::OPropertyArrayUsageHelper
664 //------------------------------------------------------------------------------
665 ::cppu::IPropertyArrayHelper* OTableColumnWrapper::createArrayHelper( sal_Int32 nId ) const
666 {
667     return OTableColumnDescriptorWrapper::createArrayHelper( nId );
668 }
669 
670