1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_dbaccess.hxx"
30 #ifndef _DBACORE_RESULTCOLUMN_HXX_
31 #include "resultcolumn.hxx"
32 #endif
33 #ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_
34 #include <com/sun/star/lang/DisposedException.hpp>
35 #endif
36 #ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATASUPPLIER_HPP_
37 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
38 #endif
39 #ifndef _COM_SUN_STAR_SDBC_DATATYPE_HPP_
40 #include <com/sun/star/sdbc/DataType.hpp>
41 #endif
42 #ifndef _COM_SUN_STAR_SDBC_COLUMNVALUE_HPP_
43 #include <com/sun/star/sdbc/ColumnValue.hpp>
44 #endif
45 #ifndef _CPPUHELPER_TYPEPROVIDER_HXX_
46 #include <cppuhelper/typeprovider.hxx>
47 #endif
48 #ifndef _TOOLS_DEBUG_HXX
49 #include <tools/debug.hxx>
50 #endif
51 #ifndef TOOLS_DIAGNOSE_EX_H
52 #include <tools/diagnose_ex.h>
53 #endif
54 #ifndef DBACCESS_SHARED_DBASTRINGS_HRC
55 #include "dbastrings.hrc"
56 #endif
57 #ifndef _DBASHARED_APITOOLS_HXX_
58 #include "apitools.hxx"
59 #endif
60 #ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_
61 #include <com/sun/star/beans/PropertyAttribute.hpp>
62 #endif
63 #ifndef _CPPUHELPER_EXC_HLP_HXX_
64 #include <cppuhelper/exc_hlp.hxx>
65 #endif
66 #ifndef _OSL_THREAD_H_
67 #include <osl/thread.h>
68 #endif
69 
70 using namespace ::com::sun::star::sdbc;
71 using namespace ::com::sun::star::beans;
72 using namespace ::com::sun::star::uno;
73 using namespace ::com::sun::star::lang;
74 using namespace ::com::sun::star::container;
75 using namespace ::osl;
76 using namespace ::comphelper;
77 using namespace ::cppu;
78 using namespace dbaccess;
79 
80 DBG_NAME(OResultColumn)
81 //--------------------------------------------------------------------------
82 OResultColumn::OResultColumn( const Reference < XResultSetMetaData >& _xMetaData, sal_Int32 _nPos,
83         const Reference< XDatabaseMetaData >& _rxDBMeta )
84     :OColumn( true )
85     ,m_xMetaData( _xMetaData )
86     ,m_xDBMetaData( _rxDBMeta )
87     ,m_nPos( _nPos )
88 {
89 	DBG_CTOR(OResultColumn,NULL);
90 }
91 // -----------------------------------------------------------------------------
92 void OResultColumn::impl_determineIsRowVersion_nothrow()
93 {
94     if ( m_aIsRowVersion.hasValue() )
95         return;
96     m_aIsRowVersion <<= (sal_Bool)(sal_False);
97 
98     OSL_ENSURE( m_xDBMetaData.is(), "OResultColumn::impl_determineIsRowVersion_nothrow: no DBMetaData!" );
99     if ( !m_xDBMetaData.is() )
100         return;
101 
102     try
103     {
104         ::rtl::OUString sCatalog, sSchema, sTable, sColumnName;
105         getPropertyValue( PROPERTY_CATALOGNAME ) >>= sCatalog;
106         getPropertyValue( PROPERTY_SCHEMANAME ) >>= sSchema;
107         getPropertyValue( PROPERTY_TABLENAME ) >>= sTable;
108         getPropertyValue( PROPERTY_NAME ) >>= sColumnName;
109 
110         try
111         {
112             Reference< XResultSet > xVersionColumns = m_xDBMetaData->getVersionColumns(
113                 makeAny( sCatalog ), sSchema, sTable );
114             if ( xVersionColumns.is() ) // allowed to be NULL
115             {
116                 Reference< XRow > xResultRow( xVersionColumns, UNO_QUERY_THROW );
117                 while ( xVersionColumns->next() )
118                 {
119                     if ( xResultRow->getString( 2 ) == sColumnName )
120                     {
121                         m_aIsRowVersion <<= (sal_Bool)(sal_True);
122                         break;
123                     }
124                 }
125             }
126         }
127         catch(const SQLException&)
128         {
129         }
130     }
131     catch( const Exception& )
132     {
133         DBG_UNHANDLED_EXCEPTION();
134     }
135 }
136 // -----------------------------------------------------------------------------
137 OResultColumn::~OResultColumn()
138 {
139 	DBG_DTOR(OResultColumn,NULL);
140 }
141 // com::sun::star::lang::XTypeProvider
142 //--------------------------------------------------------------------------
143 Sequence< sal_Int8 > OResultColumn::getImplementationId() throw (RuntimeException)
144 {
145 	static OImplementationId * pId = 0;
146 	if (! pId)
147 	{
148 		MutexGuard aGuard( Mutex::getGlobalMutex() );
149 		if (! pId)
150 		{
151 			static OImplementationId aId;
152 			pId = &aId;
153 		}
154 	}
155 	return pId->getImplementationId();
156 }
157 
158 // XServiceInfo
159 //------------------------------------------------------------------------------
160 rtl::OUString OResultColumn::getImplementationName(  ) throw(RuntimeException)
161 {
162 	return rtl::OUString::createFromAscii("com.sun.star.sdb.OResultColumn");
163 }
164 
165 //------------------------------------------------------------------------------
166 Sequence< ::rtl::OUString > OResultColumn::getSupportedServiceNames(  ) throw (RuntimeException)
167 {
168 	Sequence< ::rtl::OUString > aSNS( 2 );
169 	aSNS[0] = SERVICE_SDBCX_COLUMN;
170 	aSNS[1] = SERVICE_SDB_RESULTCOLUMN;
171 	return aSNS;
172 }
173 
174 // OComponentHelper
175 //------------------------------------------------------------------------------
176 void OResultColumn::disposing()
177 {
178 	OColumn::disposing();
179 
180 	MutexGuard aGuard(m_aMutex);
181 	m_xMetaData = NULL;
182 }
183 
184 // comphelper::OPropertyArrayUsageHelper
185 //------------------------------------------------------------------------------
186 ::cppu::IPropertyArrayHelper* OResultColumn::createArrayHelper( ) const
187 {
188 	BEGIN_PROPERTY_HELPER(21)
189 		DECL_PROP1(CATALOGNAME,				::rtl::OUString,	READONLY);
190 		DECL_PROP1(DISPLAYSIZE,				sal_Int32,			READONLY);
191 		DECL_PROP1_BOOL(ISAUTOINCREMENT,						READONLY);
192 		DECL_PROP1_BOOL(ISCASESENSITIVE,						READONLY);
193 		DECL_PROP1_BOOL(ISCURRENCY,								READONLY);
194 		DECL_PROP1_BOOL(ISDEFINITELYWRITABLE,					READONLY);
195 		DECL_PROP1(ISNULLABLE,				sal_Int32,			READONLY);
196 		DECL_PROP1_BOOL(ISREADONLY,								READONLY);
197 		DECL_PROP1_BOOL(ISROWVERSION,                           READONLY);
198 		DECL_PROP1_BOOL(ISSEARCHABLE,							READONLY);
199 		DECL_PROP1_BOOL(ISSIGNED,								READONLY);
200 		DECL_PROP1_BOOL(ISWRITABLE,								READONLY);
201 		DECL_PROP1(LABEL,					::rtl::OUString,	READONLY);
202 		DECL_PROP1(NAME,					::rtl::OUString,	READONLY);
203 		DECL_PROP1(PRECISION,				sal_Int32,			READONLY);
204 		DECL_PROP1(SCALE,					sal_Int32,			READONLY);
205 		DECL_PROP1(SCHEMANAME,				::rtl::OUString,	READONLY);
206 		DECL_PROP1(SERVICENAME,				::rtl::OUString,	READONLY);
207 		DECL_PROP1(TABLENAME,				::rtl::OUString,	READONLY);
208 		DECL_PROP1(TYPE,					sal_Int32,			READONLY);
209 		DECL_PROP1(TYPENAME,				::rtl::OUString,	READONLY);
210 	END_PROPERTY_HELPER();
211 }
212 
213 // cppu::OPropertySetHelper
214 //------------------------------------------------------------------------------
215 ::cppu::IPropertyArrayHelper& OResultColumn::getInfoHelper()
216 {
217 	return *static_cast< ::comphelper::OPropertyArrayUsageHelper< OResultColumn >* >(this)->getArrayHelper();
218 }
219 
220 //------------------------------------------------------------------------------
221 namespace
222 {
223     template< typename TYPE >
224     void obtain( Any& _out_rValue, ::boost::optional< TYPE > _rCache, const sal_Int32 _nPos, const Reference < XResultSetMetaData >& _rxResultMeta, TYPE (SAL_CALL XResultSetMetaData::*Getter)( sal_Int32 ) )
225     {
226         if ( !_rCache )
227             _rCache.reset( (_rxResultMeta.get()->*Getter)( _nPos ) );
228         _out_rValue <<= *_rCache;
229     }
230 }
231 
232 //------------------------------------------------------------------------------
233 void OResultColumn::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
234 {
235 	try
236 	{
237         if ( OColumn::isRegisteredProperty( nHandle ) )
238         {
239             OColumn::getFastPropertyValue( rValue, nHandle );
240         }
241         else
242         {
243 		    switch (nHandle)
244 		    {
245                 case PROPERTY_ID_ISROWVERSION:
246                     const_cast< OResultColumn* >( this )->impl_determineIsRowVersion_nothrow();
247                     rValue = m_aIsRowVersion;
248                     break;
249 			    case PROPERTY_ID_TABLENAME:
250 				    rValue <<= m_xMetaData->getTableName(m_nPos);
251 				    break;
252 			    case PROPERTY_ID_SCHEMANAME:
253 				    rValue <<= m_xMetaData->getSchemaName(m_nPos);
254 				    break;
255 			    case PROPERTY_ID_CATALOGNAME:
256 				    rValue <<= m_xMetaData->getCatalogName(m_nPos);
257 				    break;
258 			    case PROPERTY_ID_ISSIGNED:
259                     obtain( rValue, m_isSigned, m_nPos, m_xMetaData, &XResultSetMetaData::isSigned );
260 			        break;
261 			    case PROPERTY_ID_ISCURRENCY:
262                     obtain( rValue, m_isCurrency, m_nPos, m_xMetaData, &XResultSetMetaData::isCurrency );
263 			        break;
264 			    case PROPERTY_ID_ISSEARCHABLE:
265                     obtain( rValue, m_bSearchable, m_nPos, m_xMetaData, &XResultSetMetaData::isSearchable );
266 			        break;
267 			    case PROPERTY_ID_ISCASESENSITIVE:
268                     obtain( rValue, m_isCaseSensitive, m_nPos, m_xMetaData, &XResultSetMetaData::isCaseSensitive );
269 			        break;
270 			    case PROPERTY_ID_ISREADONLY:
271                     obtain( rValue, m_isReadOnly, m_nPos, m_xMetaData, &XResultSetMetaData::isReadOnly );
272 			        break;
273 			    case PROPERTY_ID_ISWRITABLE:
274                     obtain( rValue, m_isWritable, m_nPos, m_xMetaData, &XResultSetMetaData::isWritable );
275 			        break;
276 			    case PROPERTY_ID_ISDEFINITELYWRITABLE:
277                     obtain( rValue, m_isDefinitelyWritable, m_nPos, m_xMetaData, &XResultSetMetaData::isDefinitelyWritable );
278 			        break;
279 			    case PROPERTY_ID_ISAUTOINCREMENT:
280                     obtain( rValue, m_isAutoIncrement, m_nPos, m_xMetaData, &XResultSetMetaData::isAutoIncrement );
281 			        break;
282 			    case PROPERTY_ID_SERVICENAME:
283 				    rValue <<= m_xMetaData->getColumnServiceName(m_nPos);
284 				    break;
285 			    case PROPERTY_ID_LABEL:
286                     obtain( rValue, m_sColumnLabel, m_nPos, m_xMetaData, &XResultSetMetaData::getColumnLabel );
287 				    break;
288 			    case PROPERTY_ID_DISPLAYSIZE:
289                     obtain( rValue, m_nColumnDisplaySize, m_nPos, m_xMetaData, &XResultSetMetaData::getColumnDisplaySize );
290 				    break;
291 			    case PROPERTY_ID_TYPE:
292                     obtain( rValue, m_nColumnType, m_nPos, m_xMetaData, &XResultSetMetaData::getColumnType );
293 				    break;
294 			    case PROPERTY_ID_PRECISION:
295                     obtain( rValue, m_nPrecision, m_nPos, m_xMetaData, &XResultSetMetaData::getPrecision );
296 				    break;
297 			    case PROPERTY_ID_SCALE:
298                     obtain( rValue, m_nScale, m_nPos, m_xMetaData, &XResultSetMetaData::getScale );
299 				    break;
300 			    case PROPERTY_ID_ISNULLABLE:
301                     obtain( rValue, m_isNullable, m_nPos, m_xMetaData, &XResultSetMetaData::isNullable );
302 				    break;
303 			    case PROPERTY_ID_TYPENAME:
304 				    rValue <<= m_xMetaData->getColumnTypeName(m_nPos);
305 				    break;
306                 default:
307                     OSL_ENSURE( false, "OResultColumn::getFastPropertyValue: unknown property handle!" );
308                     break;
309             }
310 		}
311 	}
312 	catch (SQLException& )
313 	{
314 		// default handling if we caught an exception
315 		switch (nHandle)
316 		{
317 			case PROPERTY_ID_LABEL:
318 			case PROPERTY_ID_TYPENAME:
319 			case PROPERTY_ID_SERVICENAME:
320 			case PROPERTY_ID_TABLENAME:
321 			case PROPERTY_ID_SCHEMANAME:
322 			case PROPERTY_ID_CATALOGNAME:
323 				// empty string'S
324 				rValue <<= rtl::OUString();
325 				break;
326             case PROPERTY_ID_ISROWVERSION:
327 			case PROPERTY_ID_ISAUTOINCREMENT:
328 			case PROPERTY_ID_ISWRITABLE:
329 			case PROPERTY_ID_ISDEFINITELYWRITABLE:
330 			case PROPERTY_ID_ISCASESENSITIVE:
331 			case PROPERTY_ID_ISSEARCHABLE:
332 			case PROPERTY_ID_ISCURRENCY:
333 			case PROPERTY_ID_ISSIGNED:
334 			{
335 				sal_Bool bVal = sal_False;
336 				rValue.setValue(&bVal, getBooleanCppuType());
337 			}	break;
338 			case PROPERTY_ID_ISREADONLY:
339 			{
340 				sal_Bool bVal = sal_True;
341 				rValue.setValue(&bVal, getBooleanCppuType());
342 			}	break;
343 			case PROPERTY_ID_SCALE:
344 			case PROPERTY_ID_PRECISION:
345 			case PROPERTY_ID_DISPLAYSIZE:
346 				rValue <<= sal_Int32(0);
347 				break;
348 			case PROPERTY_ID_TYPE:
349 				rValue <<= sal_Int32(DataType::SQLNULL);
350 				break;
351 			case PROPERTY_ID_ISNULLABLE:
352 				rValue <<= ColumnValue::NULLABLE_UNKNOWN;
353 				break;
354 		}
355 	}
356 }
357 
358